Cómo contar el número de filas por grupo (y otras estadísticas) en pandas grupo?


Tengo un marco de datos df y uso varias columnas desde él hasta groupby:

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

De la manera anterior casi obtengo la tabla (data frame) que necesito. Lo que falta es una columna adicional que contiene el número de filas en cada grupo. En otras palabras, tengo medios, 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.

Author: Pedro M Duarte, 2013-10-15

3 answers

En el objeto groupby, la función aggpuede 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'])
 232
Author: Boud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-17 03:55:35

Respuesta rápida:

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

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


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

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


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


Ejemplo detallado:

Considere el siguiente ejemplo dataframe:

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

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

In [3]: df.groupby(['col1', 'col2']).size()
Out[3]: 
col1  col2
A     B       4
C     D       3
E     F       2
G     H       1
dtype: int64

Entonces usemos .size().reset_index(name='counts') para obtener los recuentos de filas:

In [4]: df.groupby(['col1', 'col2']).size().reset_index(name='counts')
Out[4]: 
  col1 col2  counts
0    A    B       4
1    C    D       3
2    E    F       2
3    G    H       1


Incluyendo resultados para más estadísticas

Cuando desea calcular estadísticas sobre datos agrupados, generalmente se ve así: {[19]]}

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                                   
A    B    -0.810 -1.32     4 -0.372500     4
C    D    -0.110 -1.65     3 -0.476667     3
E    F     0.475 -0.47     2  0.455000     2
G    H    -0.630 -0.63     1  1.480000     1

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

Para obtener más control sobre la salida I normalmente divido las estadísticas en agregaciones individuales que luego combino usando join. Se ve así:

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    A    B       4  -0.372500       -0.810     -1.32
1    C    D       3  -0.476667       -0.110     -1.65
2    E    F       2   0.455000        0.475     -0.47
3    G    H       1   1.480000       -0.630     -0.63



Notas a pie de página

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)
   ...: 


Descargo de responsabilidad:

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

 499
Author: Pedro M Duarte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-30 06:35:52

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

df[['col1','col2','col3','col4']].groupby(['col1','col2']).count().\
reset_index()
 4
Author: Nimesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-27 18:17:07