Pour pandas >= 0.25
La fonctionnalité permettant de nommer les colonnes agrégées retournées a été réintroduit dans la branche master et est prévue pour pandas 0.25. La nouvelle syntaxe est .agg(new_col_name=('col_name', 'agg_func')
. Exemple détaillé tiré du rapport de presse mentionné ci-dessus :
In [2]: df = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'],
...: 'height': [9.1, 6.0, 9.5, 34.0],
...: 'weight': [7.9, 7.5, 9.9, 198.0]})
...:
In [3]: df
Out[3]:
kind height weight
0 cat 9.1 7.9
1 dog 6.0 7.5
2 cat 9.5 9.9
3 dog 34.0 198.0
In [4]: df.groupby('kind').agg(min_height=('height', 'min'),
max_weight=('weight', 'max'))
Out[4]:
min_height max_weight
kind
cat 9.1 9.9
dog 6.0 198.0
Il sera également possible d'utiliser plusieurs expressions lambda avec cette syntaxe et la syntaxe de renommage en deux étapes que j'ai suggérée précédemment (ci-dessous), comme suit cette RP . Encore une fois, je copie l'exemple du PR :
In [2]: df = pd.DataFrame({"A": ['a', 'a'], 'B': [1, 2], 'C': [3, 4]})
In [3]: df.groupby("A").agg({'B': [lambda x: 0, lambda x: 1]})
Out[3]:
B
<lambda> <lambda 1>
A
a 0 1
et ensuite .rename()
ou en une seule fois :
In [4]: df.groupby("A").agg(b=('B', lambda x: 0), c=('B', lambda x: 1))
Out[4]:
b c
A
a 0 0
Pour les pandas < 0.25
La réponse actuellement acceptée par unutbu décrit une bonne façon de faire cela dans les versions de pandas <= 0.20. Cependant, à partir de pandas 0.20, l'utilisation de cette méthode soulève un avertissement indiquant que la syntaxe ne sera pas disponible dans les versions futures de pandas.
Série :
FutureWarning : l'utilisation d'un dict sur une série pour l'agrégation est obsolète et sera supprimée dans une prochaine version.
Les cadres de données :
Avertissement futur : l'utilisation d'un dict avec le renommage est dépréciée et sera supprimée dans une prochaine version.
Selon la pandas 0.20 changelog La méthode recommandée pour renommer les colonnes lors de l'agrégation est la suivante.
# Create a sample data frame
df = pd.DataFrame({'A': [1, 1, 1, 2, 2],
'B': range(5),
'C': range(5)})
# ==== SINGLE COLUMN (SERIES) ====
# Syntax soon to be deprecated
df.groupby('A').B.agg({'foo': 'count'})
# Recommended replacement syntax
df.groupby('A').B.agg(['count']).rename(columns={'count': 'foo'})
# ==== MULTI COLUMN ====
# Syntax soon to be deprecated
df.groupby('A').agg({'B': {'foo': 'sum'}, 'C': {'bar': 'min'}})
# Recommended replacement syntax
df.groupby('A').agg({'B': 'sum', 'C': 'min'}).rename(columns={'B': 'foo', 'C': 'bar'})
# As the recommended syntax is more verbose, parentheses can
# be used to introduce line breaks and increase readability
(df.groupby('A')
.agg({'B': 'sum', 'C': 'min'})
.rename(columns={'B': 'foo', 'C': 'bar'})
)
Veuillez consulter le 0.20 changelog pour plus de détails.
Mise à jour 2017-01-03 en réponse au commentaire de @JunkMechanic.
Avec l'ancienne syntaxe des dictionnaires, il était possible de passer plusieurs lambda
les fonctions de .agg
puisqu'ils seront renommés avec la clé du dictionnaire transmis :
>>> df.groupby('A').agg({'B': {'min': lambda x: x.min(), 'max': lambda x: x.max()}})
B
max min
A
1 2 0
2 4 3
Plusieurs fonctions peuvent également être transmises à une seule colonne sous la forme d'une liste :
>>> df.groupby('A').agg({'B': [np.min, np.max]})
B
amin amax
A
1 0 2
2 3 4
Cependant, cela ne fonctionne pas avec les fonctions lambda, car elles sont anonymes et renvoient toutes <lambda>
ce qui provoque une collision de noms :
>>> df.groupby('A').agg({'B': [lambda x: x.min(), lambda x: x.max]})
SpecificationError: Function names must be unique, found multiple named <lambda>
Pour éviter la SpecificationError
Les fonctions nommées peuvent être définies a priori au lieu d'utiliser des lambda
. Des noms de fonctions appropriés permettent également d'éviter d'appeler .rename
sur la base de données. Ces fonctions peuvent être transmises avec la même syntaxe de liste que ci-dessus :
>>> def my_min(x):
>>> return x.min()
>>> def my_max(x):
>>> return x.max()
>>> df.groupby('A').agg({'B': [my_min, my_max]})
B
my_min my_max
A
1 0 2
2 3 4