Tengo un marco de datos de pandas que se ve así:
mydict ={ 'person': ['Jenny', 'Jenny', 'David', 'David', 'Max', 'Max'], 'fruit': ['Apple', 'Orange', 'Apple', 'Orange', 'Apple', 'Orange'], 'eaten': [25, 75, 15, 5, 10, 10] } df = pd.DataFrame(mydict) person fruit eaten Jenny Apple 25 Jenny Orange 75 David Apple 15 David Orange 5 Max Apple 10 Max Orange 10Que me gustaría convertir en:
person apple_percentage orange_percentage Jenny 0.25 0.75 David 0.75 0.25 Max 0.50 0.50 Supongo que tendré que usar groupby de alguna manera para hacer esto, pero ¿no puedo encontrar una forma Pythonic limpia de hacerlo?
Use DataFrame.pivot con división por sum s:
df = df.pivot('person','fruit','eaten').add_suffix('_percentage') df = df.div(df.sum(axis=1), axis=0) print (df) fruit Apple_percentage Orange_percentage person David 0.75 0.25 Jenny 0.25 0.75 Max 0.50 0.50Otra opción es la tabulación cruzada de pandas:
(pd.crosstab(index = df.person, columns = df.fruit, values = df.eaten, aggfunc = 'mean', normalize='index') .add_suffix('_percentage') .rename_axis(columns=None) ) Apple_percentage Orange_percentage person David 0.75 0.25 Jenny 0.25 0.75 Max 0.50 0.50 También podría usar el método de pipe , aunque en este caso, no hace que el código sea más claro (lo que anula el propósito de la función de pipe ):
(df.assign(eaten = df.groupby('person') .pipe(lambda grp: df.eaten / grp.eaten.transform('sum')) ) .pivot('person', 'fruit', 'eaten') .add_suffix('_percentage') .rename_axis(columns=None) ) Apple_percentage Orange_percentage person David 0.75 0.25 Jenny 0.25 0.75 Max 0.50 0.50Puede apilar y desapilar () y agregar
df=df.set_index(['person','fruit']).stack().unstack('fruit').add_suffix('_percentage')#) df = df.div(df.sum(axis=1), axis=0).reset_index().drop(columns='level_1') fruit person Apple_percentage Orange_percentage 0 David 0.75 0.25 1 Jenny 0.25 0.75 2 Max 0.50 0.50