values multiple help groupby examples example columns column agg python pandas dataframe pandas-groupby aggregation

python - help - pandas group by multiple columns



AgregaciĆ³n en pandas (1)

Pregunta 1

¿Cómo realizar la agregación con pandas?

Documentación de agregación ampliada.

Las funciones de agregación son las que reducen la dimensión de los objetos devueltos. Significa que las Series / DataFrame de salida tienen menos o las mismas filas que las originales. Algunas funciones comunes de agregación se tabulan a continuación:

Function Description mean() Compute mean of groups sum() Compute sum of group values size() Compute group sizes count() Compute count of group std() Standard deviation of groups var() Compute variance of groups sem() Standard error of the mean of groups describe() Generates descriptive statistics first() Compute first of group values last() Compute last of group values nth() Take nth value, or a subset if n is a list min() Compute min of group values max() Compute max of group values

np.random.seed(123) df = pd.DataFrame({''A'' : [''foo'', ''foo'', ''bar'', ''foo'', ''bar'', ''foo''], ''B'' : [''one'', ''two'', ''three'',''two'', ''two'', ''one''], ''C'' : np.random.randint(5, size=6), ''D'' : np.random.randint(5, size=6), ''E'' : np.random.randint(5, size=6)}) print (df) A B C D E 0 foo one 2 3 0 1 foo two 4 1 0 2 bar three 2 1 1 3 foo two 1 0 3 4 bar two 3 1 4 5 foo one 2 1 0

Agregación por columnas filtradas y funciones implementadas por cython :

df1 = df.groupby([''A'', ''B''], as_index=False)[''C''].sum() print (df1) A B C 0 bar three 2 1 bar two 3 2 foo one 4 3 foo two 5

La función de agregación se usa para todas las columnas sin especificar en la función groupby , aquí columnas A, B :

df2 = df.groupby([''A'', ''B''], as_index=False).sum() print (df2) A B C D E 0 bar three 2 1 1 1 bar two 3 1 4 2 foo one 4 4 0 3 foo two 5 1 3

También puede especificar solo algunas columnas utilizadas para la agregación en la lista después de la función groupby :

df3 = df.groupby([''A'', ''B''], as_index=False)[''C'',''D''].sum() print (df3) A B C D 0 bar three 2 1 1 bar two 3 1 2 foo one 4 4 3 foo two 5 1

Los mismos resultados utilizando la función DataFrameGroupBy.agg :

df1 = df.groupby([''A'', ''B''], as_index=False)[''C''].agg(''sum'') print (df1) A B C 0 bar three 2 1 bar two 3 2 foo one 4 3 foo two 5 df2 = df.groupby([''A'', ''B''], as_index=False).agg(''sum'') print (df2) A B C D E 0 bar three 2 1 1 1 bar two 3 1 4 2 foo one 4 4 0 3 foo two 5 1 3

Para las funciones multiplicadas aplicadas para una columna, use la lista de tuple s - nombres de nuevas columnas y funciones agregadas:

df4 = (df.groupby([''A'', ''B''])[''C''] .agg([(''average'',''mean''),(''total'',''sum'')]) .reset_index()) print (df4) A B average total 0 bar three 2.0 2 1 bar two 3.0 3 2 foo one 2.0 4 3 foo two 2.5 5

Si desea pasar múltiples funciones es posible pasar la list de tuple s:

df5 = (df.groupby([''A'', ''B'']) .agg([(''average'',''mean''),(''total'',''sum'')])) print (df5) C D E average total average total average total A B bar three 2.0 2 1.0 1 1.0 1 two 3.0 3 1.0 1 4.0 4 foo one 2.0 4 2.0 4 0.0 0 two 2.5 5 0.5 1 1.5 3

A continuación, obtenga MultiIndex en columnas:

print (df5.columns) MultiIndex(levels=[[''C'', ''D'', ''E''], [''average'', ''total'']], labels=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]])

Y para convertir a columnas, aplanar MultiIndex use map con join :

df5.columns = df5.columns.map(''_''.join) df5 = df5.reset_index() print (df5) A B C_average C_total D_average D_total E_average E_total 0 bar three 2.0 2 1.0 1 1.0 1 1 bar two 3.0 3 1.0 1 4.0 4 2 foo one 2.0 4 2.0 4 0.0 0 3 foo two 2.5 5 0.5 1 1.5 3

Otra solución es pasar la lista de funciones agregadas, luego aplanar MultiIndex y para otros nombres de columnas use str.replace :

df5 = df.groupby([''A'', ''B'']).agg([''mean'',''sum'']) df5.columns = (df5.columns.map(''_''.join) .str.replace(''sum'',''total'') .str.replace(''mean'',''average'')) df5 = df5.reset_index() print (df5) A B C_average C_total D_average D_total E_average E_total 0 bar three 2.0 2 1.0 1 1.0 1 1 bar two 3.0 3 1.0 1 4.0 4 2 foo one 2.0 4 2.0 4 0.0 0 3 foo two 2.5 5 0.5 1 1.5 3

Si desea especificar cada columna con función agregada, pase el dictionary separado:

df6 = (df.groupby([''A'', ''B''], as_index=False) .agg({''C'':''sum'',''D'':''mean''}) .rename(columns={''C'':''C_total'', ''D'':''D_average''})) print (df6) A B C_total D_average 0 bar three 2 1.0 1 bar two 3 1.0 2 foo one 4 2.0 3 foo two 5 0.5

También puede pasar la función personalizada:

def func(x): return x.iat[0] + x.iat[-1] df7 = (df.groupby([''A'', ''B''], as_index=False) .agg({''C'':''sum'',''D'': func}) .rename(columns={''C'':''C_total'', ''D'':''D_sum_first_and_last''})) print (df7) A B C_total D_sum_first_and_last 0 bar three 2 2 1 bar two 3 2 2 foo one 4 4 3 foo two 5 1

Pregunta 2

Sin DataFrame después de la agregación! ¿Que pasó?

Agregación por 2 o más columnas:

df1 = df.groupby([''A'', ''B''])[''C''].sum() print (df1) A B bar three 2 two 3 foo one 4 two 5 Name: C, dtype: int32

Primero verifique el Index y el type de objeto pandas:

print (df1.index) MultiIndex(levels=[[''bar'', ''foo''], [''one'', ''three'', ''two'']], labels=[[0, 0, 1, 1], [1, 2, 0, 2]], names=[''A'', ''B'']) print (type(df1)) <class ''pandas.core.series.Series''>

Hay 2 soluciones para obtener la MultiIndex Series en columnas:

  • agregar parámetro as_index=False

df1 = df.groupby([''A'', ''B''], as_index=False)[''C''].sum() print (df1) A B C 0 bar three 2 1 bar two 3 2 foo one 4 3 foo two 5

df1 = df.groupby([''A'', ''B''])[''C''].sum().reset_index() print (df1) A B C 0 bar three 2 1 bar two 3 2 foo one 4 3 foo two 5

Si se agrupan por una columna:

df2 = df.groupby(''A'')[''C''].sum() print (df2) A bar 5 foo 9 Name: C, dtype: int32

... obtener Series con Index :

print (df2.index) Index([''bar'', ''foo''], dtype=''object'', name=''A'') print (type(df2)) <class ''pandas.core.series.Series''>

Y la solución es la misma que en la MultiIndex Series :

df2 = df.groupby(''A'', as_index=False)[''C''].sum() print (df2) A C 0 bar 5 1 foo 9 df2 = df.groupby(''A'')[''C''].sum().reset_index() print (df2) A C 0 bar 5 1 foo 9

Pregunta 3

¿Cómo agregar principalmente columnas de cadenas (para list s, tuple s, strings with separator )?

df = pd.DataFrame({''A'' : [''a'', ''c'', ''b'', ''b'', ''a'', ''c'', ''b''], ''B'' : [''one'', ''two'', ''three'',''two'', ''two'', ''one'', ''three''], ''C'' : [''three'', ''one'', ''two'', ''two'', ''three'',''two'', ''one''], ''D'' : [1,2,3,2,3,1,2]}) print (df) A B C D 0 a one three 1 1 c two one 2 2 b three two 3 3 b two two 2 4 a two three 3 5 c one two 1 6 b three one 2

En lugar de la función agregada es posible la list pases, tuple , set para convertir la columna:

df1 = df.groupby(''A'')[''B''].agg(list).reset_index() print (df1) A B 0 a [one, two] 1 b [three, two, three] 2 c [two, one]

La alternativa es utilizar GroupBy.apply :

df1 = df.groupby(''A'')[''B''].apply(list).reset_index() print (df1) A B 0 a [one, two] 1 b [three, two, three] 2 c [two, one]

Para convertir a cadenas con separador use .join solo si columna de cadena:

df2 = df.groupby(''A'')[''B''].agg('',''.join).reset_index() print (df2) A B 0 a one,two 1 b three,two,three 2 c two,one

Si la columna numérica usa la función lambda con astype para convertir a la string s:

df3 = (df.groupby(''A'')[''D''] .agg(lambda x: '',''.join(x.astype(str))) .reset_index()) print (df3) A D 0 a 1,3 1 b 3,2,2 2 c 2,1

Otra solución es convertir a cadenas antes de groupby :

df3 = (df.assign(D = df[''D''].astype(str)) .groupby(''A'')[''D''] .agg('',''.join).reset_index()) print (df3) A D 0 a 1,3 1 b 3,2,2 2 c 2,1

Para convertir todas las columnas, no pase ninguna lista de columnas después de groupby . No hay una columna D porque la exclusión automática de las columnas ''molestas'' significa que todas las columnas numéricas están excluidas.

df4 = df.groupby(''A'').agg('',''.join).reset_index() print (df4) A B C 0 a one,two three,three 1 b three,two,three two,two,one 2 c two,one one,two

Por lo tanto, es necesario convertir todas las columnas en cadenas y luego obtener todas las columnas:

df5 = (df.groupby(''A'') .agg(lambda x: '',''.join(x.astype(str))) .reset_index()) print (df5) A B C D 0 a one,two three,three 1,3 1 b three,two,three two,two,one 3,2,2 2 c two,one one,two 2,1

Pregunta 4

¿Cómo agregar cuentas?

df = pd.DataFrame({''A'' : [''a'', ''c'', ''b'', ''b'', ''a'', ''c'', ''b''], ''B'' : [''one'', ''two'', ''three'',''two'', ''two'', ''one'', ''three''], ''C'' : [''three'', np.nan, np.nan, ''two'', ''three'',''two'', ''one''], ''D'' : [np.nan,2,3,2,3,np.nan,2]}) print (df) A B C D 0 a one three NaN 1 c two NaN 2.0 2 b three NaN 3.0 3 b two two 2.0 4 a two three 3.0 5 c one two NaN 6 b three one 2.0

Función GroupBy.size para el size de cada grupo:

df1 = df.groupby(''A'').size().reset_index(name=''COUNT'') print (df1) A COUNT 0 a 2 1 b 3 2 c 2

Función GroupBy.count excluye valores perdidos:

df2 = df.groupby(''A'')[''C''].count().reset_index(name=''COUNT'') print (df2) A COUNT 0 a 2 1 b 2 2 c 1

La función se debe utilizar para varias columnas para contar valores no perdidos:

df3 = df.groupby(''A'').count().add_suffix(''_COUNT'').reset_index() print (df3) A B_COUNT C_COUNT D_COUNT 0 a 2 2 1 1 b 3 2 3 2 c 2 1 1

La función relacionada Series.value_counts devuelve el tamaño del objeto que contiene recuentos de valores únicos en orden descendente, de modo que el primer elemento es el elemento que ocurre con mayor frecuencia. Excluye los valores de NaN por defecto.

df4 = (df[''A''].value_counts() .rename_axis(''A'') .reset_index(name=''COUNT'')) print (df4) A COUNT 0 b 3 1 a 2 2 c 2

Si desea la misma salida, como usar la función groupby + size agregue Series.sort_index :

df5 = (df[''A''].value_counts() .sort_index() .rename_axis(''A'') .reset_index(name=''COUNT'')) print (df5) A COUNT 0 a 2 1 b 3 2 c 2

Pregunta 5

¿Cómo crear una nueva columna rellenada por valores agregados?

El método GroupBy.transform devuelve un objeto indexado del mismo tamaño (el mismo tamaño) que el que se está agrupando.

documentation pandas para más información.

np.random.seed(123) df = pd.DataFrame({''A'' : [''foo'', ''foo'', ''bar'', ''foo'', ''bar'', ''foo''], ''B'' : [''one'', ''two'', ''three'',''two'', ''two'', ''one''], ''C'' : np.random.randint(5, size=6), ''D'' : np.random.randint(5, size=6)}) print (df) A B C D 0 foo one 2 3 1 foo two 4 1 2 bar three 2 1 3 foo two 1 0 4 bar two 3 1 5 foo one 2 1 df[''C1''] = df.groupby(''A'')[''C''].transform(''sum'') df[''C2''] = df.groupby([''A'',''B''])[''C''].transform(''sum'') df[[''C3'',''D3'']] = df.groupby(''A'')[''C'',''D''].transform(''sum'') df[[''C4'',''D4'']] = df.groupby([''A'',''B''])[''C'',''D''].transform(''sum'') print (df) A B C D C1 C2 C3 D3 C4 D4 0 foo one 2 3 9 4 9 5 4 4 1 foo two 4 1 9 5 9 5 5 1 2 bar three 2 1 5 2 5 2 2 1 3 foo two 1 0 9 5 9 5 5 1 4 bar two 3 1 5 3 5 2 3 1 5 foo one 2 1 9 4 9 5 4 4

  1. ¿Cómo realizar la agregación con pandas?
  2. Sin DataFrame después de la agregación! ¿Que pasó?
  3. ¿Cómo agregar principalmente columnas de cadenas (para list s, tuple s, strings with separator )?
  4. ¿Cómo agregar cuentas?
  5. ¿Cómo crear una nueva columna rellenada por valores agregados?

He visto estas preguntas recurrentes sobre varias caras de la funcionalidad agregada de los pandas. La mayor parte de la información relacionada con la agregación y sus diversos casos de uso hoy en día está fragmentada en docenas de publicaciones mal redactadas y sin búsquedas. El objetivo aquí es recopilar algunos de los puntos más importantes para la posteridad.

Esta Q / A está destinada a ser la próxima entrega de una serie de guías de usuario útiles:

Tenga en cuenta que esta publicación no pretende ser un sustituto de la documentación sobre agregación y sobre groupby , ¡así que lea esto también!