sort multiple groupby examples example columns agg python pandas aggregate rename

multiple - python pandas dataframe groupby example



Cambiar el nombre de las columnas de resultados de la agregación de Pandas("FutureWarning: el uso de un dict con cambio de nombre está en desuso") (5)

Actualización para Pandas 0.25+ Reetiquetado de agregación

import pandas as pd print(pd.__version__) #0.25.0 df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"], "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0]}) df.groupby("User")[''Amount''].agg(Sum=''sum'', Count=''count'')

Salida:

Sum Count User user1 18.0 2 user2 20.5 3 user3 10.5 1

Estoy tratando de hacer algunas agregaciones en un marco de datos de pandas. Aquí hay un código de muestra:

import pandas as pd df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"], "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0]}) df.groupby(["User"]).agg({"Amount": {"Sum": "sum", "Count": "count"}}) Out[1]: Amount Sum Count User user1 18.0 2 user2 20.5 3 user3 10.5 1

Lo que genera la siguiente advertencia:

FutureWarning: el uso de un dict con cambio de nombre queda obsoleto y se eliminará en una versión futura return super (DataFrameGroupBy, self) .aggregate (arg, * args, ** kwargs)

¿Cómo puedo evitar esto?


Use groupby apply y devuelva una serie para cambiar el nombre de las columnas

Use el método groupby apply para realizar una agregación que

  • Renombra las columnas
  • Permite espacios en los nombres
  • Le permite ordenar las columnas devueltas de la forma que elija
  • Permite interacciones entre columnas
  • Devuelve un índice de nivel único y NO un índice múltiple

Para hacer esto:

  • crea una función personalizada que pasas para apply
  • Esta función personalizada se pasa a cada grupo como un DataFrame
  • Devolver una serie
  • El índice de la Serie serán las nuevas columnas.

Crea datos falsos

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1", "user3"], "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0, 9], ''Score'': [9, 1, 8, 7, 7, 6, 9]})

crear una función personalizada que devuelve una serie
La variable x dentro de my_agg es un DataFrame

def my_agg(x): names = { ''Amount mean'': x[''Amount''].mean(), ''Amount std'': x[''Amount''].std(), ''Amount range'': x[''Amount''].max() - x[''Amount''].min(), ''Score Max'': x[''Score''].max(), ''Score Sum'': x[''Score''].sum(), ''Amount Score Sum'': (x[''Amount''] * x[''Score'']).sum()} return pd.Series(names, index=[''Amount range'', ''Amount std'', ''Amount mean'', ''Score Sum'', ''Score Max'', ''Amount Score Sum''])

Pase esta función personalizada al grupo mediante el método de apply

df.groupby(''User'').apply(my_agg)

El gran inconveniente es que esta función será mucho más lenta que agg para las agregaciones cythonized

Usar un diccionario con el método groupby agg

El uso de un diccionario de diccionarios fue eliminado debido a su complejidad y naturaleza algo ambigua. Hay una discusión en curso sobre cómo mejorar esta funcionalidad en el futuro en github Aquí, puede acceder directamente a la columna de agregación después de la llamada grupal. Simplemente pase una lista de todas las funciones de agregación que desea aplicar.

df.groupby(''User'')[''Amount''].agg([''sum'', ''count''])

Salida

sum count User user1 18.0 2 user2 20.5 3 user3 10.5 1

Todavía es posible usar un diccionario para denotar explícitamente diferentes agregaciones para diferentes columnas, como aquí si hubiera otra columna numérica llamada Other .

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"], "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0], ''Other'': [1,2,3,4,5,6]}) df.groupby(''User'').agg({''Amount'' : [''sum'', ''count''], ''Other'':[''max'', ''std'']})

Salida

Amount Other sum count max std User user1 18.0 2 6 3.535534 user2 20.5 3 5 1.527525 user3 10.5 1 4 NaN


Esto es lo que hice:

Crea un conjunto de datos falso:

import pandas as pd df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1", "user3"], "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0, 9], ''Score'': [9, 1, 8, 7, 7, 6, 9]}) df

O / P:

Amount Score User 0 10.0 9 user1 1 5.0 1 user2 2 8.0 8 user2 3 10.5 7 user3 4 7.5 7 user2 5 8.0 6 user1 6 9.0 9 user3

Primero hice al Usuario el índice, y luego un grupo por:

ans = df.set_index(''User'').groupby(level=0)[''Amount''].agg([(''Sum'',''sum''),(''Count'',''count'')]) ans

Solución:

Sum Count User user1 18.0 2 user2 20.5 3 user3 19.5 2


Reemplace los diccionarios internos con una lista de funciones correctamente nombradas.

Para cambiar el nombre de la función, estoy usando esta función de utilidad:

def aliased_aggr(aggr, name): if isinstance(aggr,str): def f(data): return data.agg(aggr) else: def f(data): return aggr(data) f.__name__ = name return f

La declaración de grupo se convierte en:

df.groupby(["User"]).agg({"Amount": [ aliased_aggr("sum","Sum"), aliased_aggr("count","Count") ]

Si tiene especificaciones de agregación más grandes y reutilizables, puede convertirlas con

def convert_aggr_spec(aggr_spec): return { col : [ aliased_aggr(aggr,alias) for alias, aggr in aggr_map.items() ] for col, aggr_map in aggr_spec.items() }

Entonces puedes decir

df.groupby(["User"]).agg(convert_aggr_spec({"Amount": {"Sum": "sum", "Count": "count"}}))

Ver también https://github.com/pandas-dev/pandas/issues/18366#issuecomment-476597674


Si reemplaza el diccionario interno con una lista de tuplas, se elimina el mensaje de advertencia

import pandas as pd df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"], "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0]}) df.groupby(["User"]).agg({"Amount": [("Sum", "sum"), ("Count", "count")]})