Pandas DataFrame Group por dos columnas y obtener recuentos

166

Tengo un marco de datos de pandas en el siguiente formato:

df = pd.DataFrame([[1.1, 1.1, 1.1, 2.6, 2.5, 3.4,2.6,2.6,3.4,3.4,2.6,1.1,1.1,3.3], list('AAABBBBABCBDDD'), [1.1, 1.7, 2.5, 2.6, 3.3, 3.8,4.0,4.2,4.3,4.5,4.6,4.7,4.7,4.8], ['x/y/z','x/y','x/y/z/n','x/u','x','x/u/v','x/y/z','x','x/u/v/b','-','x/y','x/y/z','x','x/u/v/w'],['1','3','3','2','4','2','5','3','6','3','5','1','1','1']]).T
df.columns = ['col1','col2','col3','col4','col5']

df:

   col1 col2 col3     col4 col5
0   1.1    A  1.1    x/y/z    1
1   1.1    A  1.7      x/y    3
2   1.1    A  2.5  x/y/z/n    3
3   2.6    B  2.6      x/u    2
4   2.5    B  3.3        x    4
5   3.4    B  3.8    x/u/v    2
6   2.6    B    4    x/y/z    5
7   2.6    A  4.2        x    3
8   3.4    B  4.3  x/u/v/b    6
9   3.4    C  4.5        -    3
10  2.6    B  4.6      x/y    5
11  1.1    D  4.7    x/y/z    1
12  1.1    D  4.7        x    1
13  3.3    D  4.8  x/u/v/w    1

Ahora quiero agrupar esto por dos columnas como las siguientes:

df.groupby(['col5','col2']).reset_index()

Salida:

             index col1 col2 col3     col4 col5
col5 col2                                      
1    A    0      0  1.1    A  1.1    x/y/z    1
     D    0     11  1.1    D  4.7    x/y/z    1
          1     12  1.1    D  4.7        x    1
          2     13  3.3    D  4.8  x/u/v/w    1
2    B    0      3  2.6    B  2.6      x/u    2
          1      5  3.4    B  3.8    x/u/v    2
3    A    0      1  1.1    A  1.7      x/y    3
          1      2  1.1    A  2.5  x/y/z/n    3
          2      7  2.6    A  4.2        x    3
     C    0      9  3.4    C  4.5        -    3
4    B    0      4  2.5    B  3.3        x    4
5    B    0      6  2.6    B    4    x/y/z    5
          1     10  2.6    B  4.6      x/y    5
6    B    0      8  3.4    B  4.3  x/u/v/b    6

Quiero obtener el recuento de cada fila como sigue. Rendimiento esperado:

col5 col2 count
1    A      1
     D      3
2    B      2
etc...

¿Cómo obtener mi salida esperada? ¿Y quiero encontrar el recuento más grande para cada valor 'col2'?

Nilani Algiriyage
fuente
Una pregunta muy similar acaba de surgir ayer ... mira aquí .
bdiamante
Nota sobre el rendimiento, incluidas las alternativas: Pandas groupby.size vs series.value_counts vs collections.Counter with multiple series
jpp

Respuestas:

116

Seguido de la respuesta de @ Andy, puede hacer lo siguiente para resolver su segunda pregunta:

In [56]: df.groupby(['col5','col2']).size().reset_index().groupby('col2')[[0]].max()
Out[56]: 
      0
col2   
A     3
B     2
C     1
D     3
waitingkuo
fuente
1
¿Puedo obtener valores "col5" para esto como C ... 1 ... 3?
Nilani Algiriyage
141

Usted está buscando size:

In [11]: df.groupby(['col5', 'col2']).size()
Out[11]:
col5  col2
1     A       1
      D       3
2     B       2
3     A       3
      C       1
4     B       1
5     B       2
6     B       1
dtype: int64

Para obtener la misma respuesta que waitingkuo (la "segunda pregunta"), pero un poco más limpia, es agrupar por nivel:

In [12]: df.groupby(['col5', 'col2']).size().groupby(level=1).max()
Out[12]:
col2
A       3
B       2
C       1
D       3
dtype: int64
Andy Hayden
fuente
1
No sé Por qué olvidé esto: O, de todos modos, ¿qué pasa con mi segunda pregunta? ¿Encontrar el conteo más grande para cada valor "col2" y obtener el valor "col5" correspondiente?
Nilani Algiriyage
23

Insertar datos en un marco de datos de pandas y proporcionar el nombre de la columna .

import pandas as pd
df = pd.DataFrame([['A','C','A','B','C','A','B','B','A','A'], ['ONE','TWO','ONE','ONE','ONE','TWO','ONE','TWO','ONE','THREE']]).T
df.columns = [['Alphabet','Words']]
print(df)   #printing dataframe.

Estos son nuestros datos impresos:

ingrese la descripción de la imagen aquí

Para hacer un grupo de marco de datos en pandas y contador ,
debe proporcionar una columna más que cuente la agrupación, llamemos a esa columna como "CONTADOR" en el marco de datos .

Me gusta esto:

df['COUNTER'] =1       #initially, set that counter to 1.
group_data = df.groupby(['Alphabet','Words'])['COUNTER'].sum() #sum function
print(group_data)

SALIDA:

ingrese la descripción de la imagen aquí

El Gr8 Adakron
fuente
9
¿Cómo puedo hacer que la columna Alfabeto (por ejemplo, A) se repita a continuación y no dejar los espacios en la primera columna?
blissweb
¿Cómo acceder al valor de cada grupo que es la suma basada en el alfabeto y la palabra?
Rahul Goyal
21

Solución idiomática que usa solo un grupo

(df.groupby(['col5', 'col2']).size() 
   .sort_values(ascending=False) 
   .reset_index(name='count') 
   .drop_duplicates(subset='col2'))

  col5 col2  count
0    3    A      3
1    1    D      3
2    5    B      2
6    3    C      1

Explicación

El resultado del sizemétodo groupby es una Serie con col5y col2en el índice. Desde aquí, puede usar otro método groupby para encontrar el valor máximo de cada valor, col2pero no es necesario hacerlo. Simplemente puede ordenar todos los valores de mantener a descender y luego sólo las filas con la primera aparición de col2la drop_duplicatesmétodo.

Ted Petrou
fuente
No hay ningún parámetro llamado nameen reset_index()la versión actual de pandas: pandas.pydata.org/pandas-docs/stable/generated/…
mmBs
Ok, mi mal Lo usé cuando trabajaba con DataFrameno Series. Gracias por el enlace.
mmBs
2

Si desea agregar una nueva columna (por ejemplo, 'cuenta_columna') que contiene los recuentos de los grupos en el marco de datos:

df.count_column=df.groupby(['col5','col2']).col5.transform('count')

(Elegí 'col5' ya que no contiene nan)

Tom
fuente
-2

Puede usar el recuento de funciones incorporado seguido de la función groupby

df.groupby(['col5','col2']).count()
seansio1995
fuente