Múltiples agregaciones de la misma columna usando pandas GroupBy.agg ()

Dado el siguiente cuadro de datos (totalmente exagerado)

import pandas as pd import datetime as dt df = pd.DataFrame({ "date" : [dt.date(2012, x, 1) for x in range(1, 11)], "returns" : 0.05 * np.random.randn(10), "dummy" : np.repeat(1, 10) }) 

¿Existe una forma integrada para aplicar dos funciones de agregación diferentes a la misma columna, sin tener que llamar a agg varias veces?

La forma sintácticamente incorrecta, pero intuitivamente correcta, sería:

 # Assume `function1` and `function2` are defined for aggregating. df.groupby("dummy").agg({"returns":function1, "returns":function2}) 

Obviamente, Python no permite claves duplicadas. ¿Hay alguna otra manera de express la entrada a agg ? ¿Quizás una lista de tuplas [(column, function)] funcionaría mejor, para permitir múltiples funciones aplicadas a la misma columna? Pero parece que solo acepta un diccionario.

¿Hay una solución para esto además de definir una función auxiliar que solo aplique ambas funciones dentro de ella? (¿Cómo funcionaría esto con la agregación de todos modos?)

Simplemente puede pasar las funciones como una lista:

 In [20]: df.groupby("dummy").agg({"returns": [np.mean, np.sum]}) Out[20]: returns sum mean dummy 1 0.285833 0.028583 

o como un diccionario:

 In [21]: df.groupby('dummy').agg({'returns': {'Mean': np.mean, 'Sum': np.sum}}) Out[21]: returns Sum Mean dummy 1 0.285833 0.028583 

Algo como esto funcionaría:

 In [7]: df.groupby('dummy').returns.agg({'func1' : lambda x: x.sum(), 'func2' : lambda x: x.prod()}) Out[7]: func2 func1 dummy 1 -4.263768e-16 -0.188565 

Una forma obvia de hacer esto es especificando los nombres de las columnas de mapeo de un diccionario a una lista de funciones para agregar con:

 df.groupby("dummy").agg({'returns': [function1, function2]}) 

 df.groupby("dummy").agg({'returns': ['sum', 'mean']}) returns sum mean dummy 1 0.328953 0.032895 

Sin embargo, si sus funciones solo operan en la columna, la syntax es un poco más simple: no se necesita un diccionario si se agrega en una Serie:

 df.groupby("dummy")['returns'].agg([function1, function2]) 

 df.groupby('dummy')['returns'].agg(['sum', 'mean']) sum mean dummy 1 0.328953 0.032895 

Esto también elimina el MultiIndex en la salida.


En versiones más recientes de pandas, si usa un diccionario para especificar nombres de columnas para el resultado de agregación, obtendrá un FutureWarning :

 df.groupby('dummy').agg({'returns': {'Mean': 'mean', 'Sum': 'sum'}}) # FutureWarning: using a dict with renaming is deprecated and will be removed # in a future version 

El uso de un diccionario para renombrar columnas está en desuso en v0.20. En versiones más recientes de pandas, esto se puede especificar más simplemente al pasar una lista de tuplas. Si se especifican las funciones de esta manera, todas las funciones para esa columna deben especificarse como tuplas de pares (nombre, función).

 df.groupby("dummy").agg({'returns': [('op1', 'sum'), ('op2', 'mean')]}) returns op1 op2 dummy 1 0.328953 0.032895 

O,

 df.groupby("dummy")['returns'].agg([('op1', 'sum'), ('op2', 'mean')]) op1 op2 dummy 1 0.328953 0.032895