Obtenga estadísticas para cada grupo (como conteo, media, etc.) usando pandas GroupBy?

Tengo un df dataframe y uso varias columnas de él para groupby :

 df['col1','col2','col3','col4'].groupby(['col1','col2']).mean() 

De la forma anterior casi consigo la tabla (dataframe) que necesito. Lo que falta es una columna adicional que contenga el número de filas en cada grupo. En otras palabras, quiero decir, pero también me gustaría saber cuántos números se utilizaron para obtener estos medios. Por ejemplo, en el primer grupo hay 8 valores y en el segundo 10 y así sucesivamente.

En resumen: ¿Cómo obtengo estadísticas por grupo para un dataframe?

En el objeto groupby , la función agg puede tomar una lista para aplicar varios métodos de agregación a la vez. Esto debería darte el resultado que necesitas:

 df[['col1', 'col2', 'col3', 'col4']].groupby(['col1', 'col2']).agg(['mean', 'count']) 

Respuesta rápida:

La forma más sencilla de obtener recuentos de filas por grupo es llamando a .size() , que devuelve una Series :

 df.groupby(['col1','col2']).size() 

Por lo general, desea que este resultado sea un DataFrame (en lugar de una Series ) para que pueda hacer:

 df.groupby(['col1', 'col2']).size().reset_index(name='counts') 

Si desea saber cómo calcular los recuentos de filas y otras estadísticas para cada grupo, siga leyendo a continuación.


Ejemplo detallado:

Considere el siguiente dataframe de ejemplo:

 In [2]: df Out[2]: col1 col2 col3 col4 col5 col6 0 AB 0.20 -0.61 -0.49 1.49 1 AB -1.53 -1.01 -0.39 1.82 2 AB -0.44 0.27 0.72 0.11 3 AB 0.28 -1.32 0.38 0.18 4 CD 0.12 0.59 0.81 0.66 5 CD -0.13 -1.65 -1.64 0.50 6 CD -1.42 -0.11 -0.18 -0.44 7 EF -0.00 1.42 -0.26 1.17 8 EF 0.91 -0.47 1.35 -0.34 9 GH 1.48 -0.63 -1.14 0.17 

Primero, usemos .size() para obtener los conteos de filas:

 In [3]: df.groupby(['col1', 'col2']).size() Out[3]: col1 col2 AB 4 CD 3 EF 2 GH 1 dtype: int64 

Luego, usemos .size().reset_index(name='counts') para obtener los conteos de filas:

 In [4]: df.groupby(['col1', 'col2']).size().reset_index(name='counts') Out[4]: col1 col2 counts 0 AB 4 1 CD 3 2 EF 2 3 GH 1 

Incluyendo resultados para más estadísticas

Cuando desea calcular estadísticas sobre datos agrupados, generalmente se ve así:

 In [5]: (df ...: .groupby(['col1', 'col2']) ...: .agg({ ...: 'col3': ['mean', 'count'], ...: 'col4': ['median', 'min', 'count'] ...: })) Out[5]: col4 col3 median min count mean count col1 col2 AB -0.810 -1.32 4 -0.372500 4 CD -0.110 -1.65 3 -0.476667 3 EF 0.475 -0.47 2 0.455000 2 GH -0.630 -0.63 1 1.480000 1 

El resultado anterior es un poco molesto de tratar debido a las tags de columna anidadas, y también porque los recuentos de filas se realizan por columna.

Para obtener un mayor control sobre la salida, normalmente divido las estadísticas en agregaciones individuales que luego combino usando join . Se parece a esto:

 In [6]: gb = df.groupby(['col1', 'col2']) ...: counts = gb.size().to_frame(name='counts') ...: (counts ...: .join(gb.agg({'col3': 'mean'}).rename(columns={'col3': 'col3_mean'})) ...: .join(gb.agg({'col4': 'median'}).rename(columns={'col4': 'col4_median'})) ...: .join(gb.agg({'col4': 'min'}).rename(columns={'col4': 'col4_min'})) ...: .reset_index() ...: ) ...: Out[6]: col1 col2 counts col3_mean col4_median col4_min 0 AB 4 -0.372500 -0.810 -1.32 1 CD 3 -0.476667 -0.110 -1.65 2 EF 2 0.455000 0.475 -0.47 3 GH 1 1.480000 -0.630 -0.63 


Notas al pie

El código utilizado para generar los datos de prueba se muestra a continuación:

 In [1]: import numpy as np ...: import pandas as pd ...: ...: keys = np.array([ ...: ['A', 'B'], ...: ['A', 'B'], ...: ['A', 'B'], ...: ['A', 'B'], ...: ['C', 'D'], ...: ['C', 'D'], ...: ['C', 'D'], ...: ['E', 'F'], ...: ['E', 'F'], ...: ['G', 'H'] ...: ]) ...: ...: df = pd.DataFrame( ...: np.hstack([keys,np.random.randn(10,4).round(2)]), ...: columns = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6'] ...: ) ...: ...: df[['col3', 'col4', 'col5', 'col6']] = \ ...: df[['col3', 'col4', 'col5', 'col6']].astype(float) ...: 

Renuncia:

Si algunas de las columnas que está agregando tienen valores nulos, entonces realmente desea observar los recuentos de filas de grupo como una agregación independiente para cada columna. De lo contrario, puede ser engañado en cuanto a la cantidad de registros que realmente se están utilizando para calcular cosas como la media porque los pandas eliminarán las entradas de NaN en el cálculo de la media sin informarle al respecto.

Podemos hacerlo fácilmente usando groupby y contar. Pero, debemos recordar utilizar reset_index ().

 df[['col1','col2','col3','col4']].groupby(['col1','col2']).count().\ reset_index() 

Una función para gobernarlos a todos: GroupBy.describe

Las estadísticas de count , mean , std y otras estadísticas útiles por grupo.

 df.groupby(['col1', 'col2'])['col3', 'col4'].describe() 

 # Setup np.random.seed(0) df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'], 'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'], 'C' : np.random.randn(8), 'D' : np.random.randn(8)}) 

 from IPython.display import display with pd.option_context('precision', 2): display(df.groupby(['A', 'B'])['C'].describe()) count mean std min 25% 50% 75% max AB bar one 1.0 0.40 NaN 0.40 0.40 0.40 0.40 0.40 three 1.0 2.24 NaN 2.24 2.24 2.24 2.24 2.24 two 1.0 -0.98 NaN -0.98 -0.98 -0.98 -0.98 -0.98 foo one 2.0 1.36 0.58 0.95 1.15 1.36 1.56 1.76 three 1.0 -0.15 NaN -0.15 -0.15 -0.15 -0.15 -0.15 two 2.0 1.42 0.63 0.98 1.20 1.42 1.65 1.87 

Para obtener estadísticas específicas, simplemente selecciónelos,

 df.groupby(['A', 'B'])['C'].describe()[['count', 'mean']] count mean AB bar one 1.0 0.400157 three 1.0 2.240893 two 1.0 -0.977278 foo one 2.0 1.357070 three 1.0 -0.151357 two 2.0 1.423148 

describe trabajos para varias columnas (cambie ['C'] a ['C', 'D'] y vea lo que sucede, el resultado es un dataframe de columnas con múltiples índices).

Para más información, consulte la documentación .