python - type - dplyr resumen equivalente en pandas
pandas summary (2)
Consulte la comparación lado a lado proporcionada por la documentación de Pandas aquí: http://pandas.pydata.org/pandas-docs/stable/comparison_with_r.html#grouping-and-summarizing
D''sr de R
gdf <- group_by(df, col1)
summarise(gdf, avg=mean(col1, na.rm=TRUE))
Pandas
gdf = df.groupby(''col1'')
df.groupby(''col1'').agg({''col1'': ''mean''})
Solía trabajar con R y realmente me encanta el paquete dplyr que puede agrupar y resumir fácilmente.
Sin embargo, en pandas, no veo un equivalente de resumen y aquí es cómo lo logro en Python:
import pandas as pd
data = pd.DataFrame(
{''col1'':[1,1,1,1,1,2,2,2,2,2],
''col2'':[1,2,3,4,5,6,7,8,9,0],
''col3'':[-1,-2,-3,-4,-5,-6,-7,-8,-9,0]
}
)
result = []
for k,v in data.groupby(''col1''):
result.append([k, max(v[''col2'']), min(v[''col3''])])
print pd.DataFrame(result, columns=[''col1'', ''col2_agg'', ''col3_agg''])
No solo es muy detallado, sino que puede que no sea el más optimizado y eficiente. (Solía reescribir una implementación de for loop groupby
en groupby.agg
y la mejora de rendimiento era enorme).
En R el código será
data %>% groupby(col1) %>% summarize(col2_agg=max(col2), col3_agg=min(col3))
¿Hay un equivalente eficiente en Python o para bucle? Es con lo que tengo que trabajar.
también, @ayhan realmente dio una solución a mi respuesta, esta es una pregunta de seguimiento que enumeraré aquí en lugar del comentario:
cuál es el equivalente de groupby().summarize(newcolumn=max(col2 * col3))
El equivalente de
df %>% groupby(col1) %>% summarize(col2_agg=max(col2), col3_agg=min(col3))
es
df.groupby(''col1'').agg({''col2'': ''max'', ''col3'': ''min''})
que devuelve
col2 col3
col1
1 5 -5
2 9 -9
El objeto devuelto es un pandas.DataFrame con un índice llamado col1
y columnas llamadas col2
y col2
. De forma predeterminada, cuando agrupa sus datos, los pandas establecen la (s) columna (s) de agrupación como índice para un acceso y modificación eficientes. Sin embargo, si no quieres eso, hay dos alternativas para establecer col1
como una columna.
Pase
as_index=False
:df.groupby(''col1'', as_index=False).agg({''col2'': ''max'', ''col3'': ''min''})
Llamar
reset_index
:df.groupby(''col1'').agg({''col2'': ''max'', ''col3'': ''min''}).reset_index()
ambos ceden
col1 col2 col3
1 5 -5
2 9 -9
También puede pasar múltiples funciones a groupby.agg
.
agg_df = df.groupby(''col1'').agg({''col2'': [''max'', ''min'', ''std''],
''col3'': [''size'', ''std'', ''mean'', ''max'']})
Esto también devuelve un DataFrame pero ahora tiene un MultiIndex para columnas.
col2 col3
max min std size std mean max
col1
1 5 1 1.581139 5 1.581139 -3 -1
2 9 0 3.535534 5 3.535534 -6 0
MultiIndex es muy útil para la selección y agrupación. Aquí hay unos ejemplos:
agg_df[''col2''] # select the second column
max min std
col1
1 5 1 1.581139
2 9 0 3.535534
agg_df[(''col2'', ''max'')] # select the maximum of the second column
Out:
col1
1 5
2 9
Name: (col2, max), dtype: int64
agg_df.xs(''max'', axis=1, level=1) # select the maximum of all columns
Out:
col2 col3
col1
1 5 -1
2 9 0
Anteriormente (antes de la versión 0.20.0 ) era posible usar diccionarios para cambiar el nombre de las columnas en la llamada agg
. Por ejemplo
df.groupby(''col1'')[''col2''].agg({''max_col2'': ''max''})
devolvería el máximo de la segunda columna como max_col2
:
max_col2
col1
1 5
2 9
Sin embargo, fue desaprobado a favor del método de cambio de nombre:
df.groupby(''col1'')[''col2''].agg([''max'']).rename(columns={''max'': ''col2_max''})
col2_max
col1
1 5
2 9
Puede ser detallado para un DataFrame como agg_df
definido anteriormente. Puede usar una función de cambio de nombre para aplanar esos niveles en ese caso:
agg_df.columns = [''_''.join(col) for col in agg_df.columns]
col2_max col2_min col2_std col3_size col3_std col3_mean col3_max
col1
1 5 1 1.581139 5 1.581139 -3 -1
2 9 0 3.535534 5 3.535534 -6 0
Para operaciones como groupby().summarize(newcolumn=max(col2 * col3))
, aún puede usar agg agregando primero una nueva columna con assign
.
df.assign(new_col=df.eval(''col2 * col3'')).groupby(''col1'').agg(''max'')
col2 col3 new_col
col1
1 5 -1 -1
2 9 0 0
Esto devuelve el máximo para las columnas antiguas y nuevas, pero como siempre puede dividir eso.
df.assign(new_col=df.eval(''col2 * col3'')).groupby(''col1'')[''new_col''].agg(''max'')
col1
1 -1
2 0
Name: new_col, dtype: int64
Con groupby.apply
esto sería más corto:
df.groupby(''col1'').apply(lambda x: (x.col2 * x.col3).max())
col1
1 -1
2 0
dtype: int64
Sin embargo, groupby.apply
trata esto como una función personalizada por lo que no se vectoriza. Hasta ahora, las funciones que pasamos a agg
(''min'', ''max'', ''min'', ''tamaño'', etc.) están vectorizadas y son alias para esas funciones optimizadas. Puede reemplazar df.groupby(''col1'').agg(''min'')
con df.groupby(''col1'').agg(min)
, df.groupby(''col1'').agg(np.min)
o df.groupby(''col1'').min()
y todos ejecutarán la misma función. No verá la misma eficiencia cuando use funciones personalizadas.
Finalmente, a partir de la versión 0.20, agg
se puede usar directamente en DataFrames, sin tener que agrupar primero. Vea ejemplos here .