Dans l'exemple de la documentation pandas sur la nouvelle méthode .pipe()
pour les objets GroupBy, une méthode .apply()
acceptant le même lambda retournerait les mêmes résultats.
In [195]: import numpy as np
In [196]: n = 1000
In [197]: df = pd.DataFrame({'Store': np.random.choice(['Store_1', 'Store_2'], n),
.....: 'Product': np.random.choice(['Product_1', 'Product_2', 'Product_3'], n),
.....: 'Revenue': (np.random.random(n)*50+10).round(2),
.....: 'Quantity': np.random.randint(1, 10, size=n)})
In [199]: (df.groupby(['Store', 'Product'])
.....: .pipe(lambda grp: grp.Revenue.sum()/grp.Quantity.sum())
.....: .unstack().round(2))
Out[199]:
Product Product_1 Product_2 Product_3
Store
Store_1 6.93 6.82 7.15
Store_2 6.69 6.64 6.77
Je peux voir en quoi la fonctionnalité pipe
diffère de apply
pour les objets DataFrame, mais pas pour les objets GroupBy. Quelqu'un at-il une explication ou des exemples de ce qui peut être fait avec pipe
mais pas avec apply
pour un GroupBy?
Ce que pipe
fait est de vous permettre de passer un appelable avec l'espoir que l'objet qui a appelé pipe
est l'objet qui est passé à l'appelable.
Avec apply
, nous supposons que l'objet qui appelle apply
a des sous-composants qui seront chacun transmis à l'appelable qui a été passé à apply
. Dans le contexte d'un groupby
, les sous-composants sont des tranches de la trame de données qui ont appelé groupby
où chaque tranche est une trame de données elle-même. Ceci est analogue à une série groupby
.
La principale différence entre ce que vous pouvez faire avec un pipe
dans un contexte groupby
est que vous avez à la disposition de l'appelable toute la portée de l'objet groupby
. Pour postuler, vous ne connaissez que la tranche locale.
Configuration
Considérez df
df = pd.DataFrame(dict(
A=list('XXXXYYYYYY'),
B=range(10)
))
A B
0 X 0
1 X 1
2 X 2
3 X 3
4 Y 4
5 Y 5
6 Y 6
7 Y 7
8 Y 8
9 Y 9
exemple 1
Réalisez l'ensemble 'B'
somme de la colonne à 1
tandis que chaque sous-groupe totalise le même montant. Cela nécessite que le calcul sache combien de groupes existent. C'est quelque chose que nous ne pouvons pas faire avec apply
parce que apply
ne saurait pas combien de groupes existent.
s = df.groupby('A').B.pipe(lambda g: df.B / g.transform('sum') / g.ngroups)
s
0 0.000000
1 0.083333
2 0.166667
3 0.250000
4 0.051282
5 0.064103
6 0.076923
7 0.089744
8 0.102564
9 0.115385
Name: B, dtype: float64
Remarque:
s.sum()
0.99999999999999989
Et:
s.groupby(df.A).sum()
A
X 0.5
Y 0.5
Name: B, dtype: float64
Exemple 2
Soustrayez la moyenne d'un groupe des valeurs d'un autre. Encore une fois, cela ne peut pas être fait avec apply
car apply
ne connaît pas les autres groupes.
df.groupby('A').B.pipe(
lambda g: (
g.get_group('X') - g.get_group('Y').mean()
).append(
g.get_group('Y') - g.get_group('X').mean()
)
)
0 -6.5
1 -5.5
2 -4.5
3 -3.5
4 2.5
5 3.5
6 4.5
7 5.5
8 6.5
9 7.5
Name: B, dtype: float64