df1 = pd.DataFrame({'foo': ['one', 'one', 'one', 'two', 'two', 'two'], 'bar': ['A', 'B', 'C', 'A', 'B', 'C']})| Foo | bar | |
|---|---|---|
| 0 | una | A |
| 1 | una | B |
| 2 | una | C |
| 3 | dos | A |
| 4 | dos | B |
| 5 | dos | C |
Me gustaría convertir esto en
| Foo | val1 | val2 | val3 |
|---|---|---|---|
| Una | A | B | C |
| Dos | A | B | C |
Y el código que probé es:
pd.pivot_table(df1,index='foo',aggfunc=['first'])Pero el código anterior devuelve solo el primer valor
Podemos enumerar grupos con groupby cumcount y usarlos como columnas pivote, luego add_prefix a los valores numéricos y reset_index para devolver los valores 'foo' a las columnas:
new_df = ( df1.pivot_table(index='foo', columns=df1.groupby('foo').cumcount() + 1, values='bar', aggfunc='first') .add_prefix('val') .reset_index() ) foo val1 val2 val3 0 one ABC 1 two ABC Vea cómo df1.groupby('foo').cumcount() + 1 hace las columnas:
foo columns 0 one 1 # First instance of "one" 1 one 2 # Second instance of "one" 2 one 3 # Third instance of "one" 3 two 1 4 two 2 5 two 3Código para generar el marco de datos anterior:
demo_df = pd.DataFrame({ 'foo': df1['foo'], 'columns': df1.groupby('foo').cumcount() + 1 })Otra solución:
x = df1.pivot("foo", "bar", "bar") x.columns = [f"var{i}" for i in range(1, len(x.columns) + 1)] x = x.reset_index() print(x)Huellas dactilares:
foo var1 var2 var3 0 one ABC 1 two ABCTratar:
df1.groupby([df1.groupby('foo').cumcount() + 1, 'foo']).first()['bar'].unstack(0).add_prefix('val').reset_index()Producción:
foo val1 val2 val3 0 one ABC 1 two ABCdf1 = pd.DataFrame({'foo': ['one', 'one', 'one', 'two', 'two', 'two'], 'bar': ['A', 'B', 'C', 'A', 'B', 'C']}) df1['i'] = df1['bar'].apply(lambda x: "val "+x) pd.pivot(df1,index='foo',columns='i',values='bar')pd.pivot_table(df1,index='foo',columns=df1.groupby(df1.foo).cumcount()+1, values='bar',aggfunc=(lambda x:min(x)), dropna=True).add_prefix('val')producción:
val1 val2 val 3 foo one ABC two ABCSiguiendo el ejemplo de la solución de @HenryEcker, una combinación de groupby y pivote puede obtener el resultado:
(df1.assign(counter = lambda df: df.groupby('foo').cumcount()) .pivot('foo', 'counter', 'bar') .rename(columns = lambda col: f"val{col}" if col!=0 else "val") .rename_axis(columns=None) ) val val1 val2 foo one ABC two ABC