dplyr resumen equivalente en pandas

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 a 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ás la misma eficiencia cuando uses funciones personalizadas.

Por último, a partir de la versión 0.20, agg se puede usar directamente en DataFrames, sin tener que agrupar primero. Vea ejemplos aquí .

Verifique la comparación en paralelo 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'})