web-dev-qa-db-fra.com

Agrégations multiples de la même colonne à l'aide de pandas GroupBy.agg ()

Étant donné l'exemple de bloc de données suivant (totalement excessif)

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-t-il une méthode intégrée permettant d'appliquer deux fonctions d'agrégation différentes à la même colonne sans avoir à appeler agg plusieurs fois? 

La façon de le faire, syntaxiquement, mais intuitivement, serait la suivante:

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

De toute évidence, Python n'autorise pas les clés en double. Existe-t-il un autre moyen d'exprimer l'entrée dans agg? Peut-être qu'une liste de tuples [(column, function)] fonctionnerait mieux pour autoriser plusieurs fonctions appliquées à la même colonne? Mais il semble qu’il n’accepte qu’un dictionnaire.

Existe-t-il une solution de contournement pour cela en plus de définir une fonction auxiliaire qui applique uniquement les deux fonctions internes? (Comment cela fonctionnerait-il avec l'agrégation de toute façon?)

61
ely

Vous pouvez simplement passer les fonctions sous forme de liste:

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

dummy                    
1      0.285833  0.028583

ou comme dictionnaire:

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

Est-ce que quelque chose comme ce travail:

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
5
Chang She

Une façon évidente de le faire consiste à spécifier un nom de colonne de mappage de dictionnaire dans une liste de fonctions à agréger avec:

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

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

        returns          
            sum      mean
dummy                    
1      0.328953  0.032895

Cependant, si vos fonctions ne fonctionnent que sur la colonne, la syntaxe est un peu plus simple: un dictionnaire n'est pas nécessaire si vous effectuez une agrégation sur une série:

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

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

            sum      mean
dummy                    
1      0.328953  0.032895

Cela élimine également le MultiIndex dans la sortie.


Dans les versions plus récentes des pandas, si vous utilisez un dictionnaire pour spécifier les noms de colonne pour la sortie d'agrégation, vous obtiendrez une 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

L'utilisation d'un dictionnaire pour renommer des colonnes est obsolète en v0.20. Sur les versions plus récentes des pandas, ceci peut être spécifié plus simplement en passant une liste de n-uplets. Si vous spécifiez les fonctions de cette façon, les fonctions all de cette colonne doivent être spécifiées en tant que tuples de paires (nom, fonction).

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

        returns          
            op1       op2
dummy                    
1      0.328953  0.032895

Ou,

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

            op1       op2
dummy                    
1      0.328953  0.032895
0
coldspeed