web-dev-qa-db-fra.com

Quelle est la difference entre pandas agg et apply function?

Je ne peux pas comprendre la différence entre les fonctions Pandas .aggregate et .apply.
Prenons l'exemple suivant: je charge un jeu de données, crée une variable groupby, définit une fonction simple et l'utilisateur .agg ou .apply.

Comme vous pouvez le constater, l'instruction d'impression dans ma fonction produit le même résultat après l'utilisation de .agg et .apply. Le résultat, en revanche, est différent. Pourquoi donc?

import pandas
import pandas as pd
iris = pd.read_csv('iris.csv')
by_species = iris.groupby('Species')
def f(x):
    ...:     print type(x)
    ...:     print x.head(3)
    ...:     return 1

Utilisation de apply:

by_species.apply(f)
#<class 'pandas.core.frame.DataFrame'>
#   Sepal.Length  Sepal.Width  Petal.Length  Petal.Width Species
#0           5.1          3.5           1.4          0.2  setosa
#1           4.9          3.0           1.4          0.2  setosa
#2           4.7          3.2           1.3          0.2  setosa
#<class 'pandas.core.frame.DataFrame'>
#   Sepal.Length  Sepal.Width  Petal.Length  Petal.Width Species
#0           5.1          3.5           1.4          0.2  setosa
#1           4.9          3.0           1.4          0.2  setosa
#2           4.7          3.2           1.3          0.2  setosa
#<class 'pandas.core.frame.DataFrame'>
#    Sepal.Length  Sepal.Width  Petal.Length  Petal.Width     Species
#50           7.0          3.2           4.7          1.4  versicolor
#51           6.4          3.2           4.5          1.5  versicolor
#52           6.9          3.1           4.9          1.5  versicolor
#<class 'pandas.core.frame.DataFrame'>
#     Sepal.Length  Sepal.Width  Petal.Length  Petal.Width    Species
#100           6.3          3.3           6.0          2.5  virginica
#101           5.8          2.7           5.1          1.9  virginica
#102           7.1          3.0           5.9          2.1  virginica
#Out[33]: 
#Species
#setosa        1
#versicolor    1
#virginica     1
#dtype: int64

Utiliser agg

by_species.agg(f)
#<class 'pandas.core.frame.DataFrame'>
#   Sepal.Length  Sepal.Width  Petal.Length  Petal.Width Species
#0           5.1          3.5           1.4          0.2  setosa
#1           4.9          3.0           1.4          0.2  setosa
#2           4.7          3.2           1.3          0.2  setosa
#<class 'pandas.core.frame.DataFrame'>
#    Sepal.Length  Sepal.Width  Petal.Length  Petal.Width     Species
#50           7.0          3.2           4.7          1.4  versicolor
#51           6.4          3.2           4.5          1.5  versicolor
#52           6.9          3.1           4.9          1.5  versicolor
#<class 'pandas.core.frame.DataFrame'>
#     Sepal.Length  Sepal.Width  Petal.Length  Petal.Width    Species
#100           6.3          3.3           6.0          2.5  virginica
#101           5.8          2.7           5.1          1.9  virginica
#102           7.1          3.0           5.9          2.1  virginica
#Out[34]: 
#           Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
#Species                                                         
#setosa                 1            1             1            1
#versicolor             1            1             1            1
#virginica              1            1             1            1
18
David D

apply applique la fonction à chaque groupe (votre Species). Votre fonction renvoie 1, vous obtenez donc une valeur pour chacun des 3 groupes.

agg agrégats chaque colonne (fonctionnalité) pour chaque groupe, vous obtenez donc une valeur par colonne et par groupe.

Lisez les groupby docs, ils sont très utiles. Il existe également un ensemble de tutoriels flottant sur le Web.

25
TomAugspurger

(Remarque: Ces comparaisons sont pertinentes pour les objets DataframeGroupby)

Certains {avantages de l’utilisation de .agg ()} par rapport à .apply (), pour les objets DataFrame GroupBy plausibles seraient:

1) .agg () donne la flexibilité de appliquer plusieurs fonctions à la fois}, ou transmet une liste de fonctions à chaque colonne.

2) De même, appliquant différentes fonctions en même temps à différentes colonnes de dataframe.

Cela signifie que vous avez à peu près le contrôle de chaque colonne avec chaque opération.

Voici le lien pour plus de détails: http://pandas.pydata.org/pandas-docs/version/0.13.1/groupby.html

Toutefois, la fonction d'application peut être limitée à l'application d'une fonction à chaque colonne du cadre de données à la fois. Ainsi, vous devrez peut-être appeler la fonction apply à plusieurs reprises pour appeler différentes opérations sur la même colonne.

Voici quelques exemples de comparaison pour .apply () vs .agg () pour les objets DataframeGroupBy: 

Voyons tout d'abord les opérations utilisant .apply ():

In [261]: df = pd.DataFrame({"name":["Foo", "Baar", "Foo", "Baar"], "score_1":[5,10,15,10], "score_2" :[10,15,10,25], "score_3" : [10,20,30,40]})

In [262]: df
Out[262]: 
   name  score_1  score_2  score_3
0   Foo        5       10       10
1  Baar       10       15       20
2   Foo       15       10       30
3  Baar       10       25       40

In [263]: df.groupby(["name", "score_1"])["score_2"].apply(lambda x : x.sum())
Out[263]: 
name  score_1
Baar  10         40
Foo   5          10
      15         10
Name: score_2, dtype: int64

In [264]: df.groupby(["name", "score_1"])["score_2"].apply(lambda x : x.min())
Out[264]: 
name  score_1
Baar  10         15
Foo   5          10
      15         10
Name: score_2, dtype: int64

In [265]: df.groupby(["name", "score_1"])["score_2"].apply(lambda x : x.mean())
Out[265]: 
name  score_1
Baar  10         20.0
Foo   5          10.0
      15         10.0
Name: score_2, dtype: float64

Maintenant, regardez les mêmes opérations utilisant .agg () sans effort:

In [274]: df = pd.DataFrame({"name":["Foo", "Baar", "Foo", "Baar"], "score_1":[5,10,15,10], "score_2" :[10,15,10,25], "score_3" : [10,20,30,40]})

In [275]: df
Out[275]: 
   name  score_1  score_2  score_3
0   Foo        5       10       10
1  Baar       10       15       20
2   Foo       15       10       30
3  Baar       10       25       40

In [276]: df.groupby(["name", "score_1"]).agg({"score_3" :[np.sum, np.min, np.mean, np.max], "score_2":lambda x : x.mean()})
Out[276]: 
              score_2 score_3               
             <lambda>     sum amin mean amax
name score_1                                
Baar 10            20      60   20   30   40
Foo  5             10      10   10   10   10
     15            10      30   30   30   30

Ainsi, .agg () pourrait être très pratique pour gérer les objets DataFrameGroupBy, par rapport à .apply (). Mais, si vous ne gérez que des objets dataframe purs, et non des objets DataFrameGroupBy, alors apply () peut s'avérer très utile car apply () peut appliquer une fonction le long de n'importe quel axe du dataframe.

(Par exemple: axe = 0 implique une opération de type colonne avec .apply (), qui est un mode par défaut, et un axe = 1 impliquerait pour une opération relative à une ligne tout en traitant des objets de données pures )

9
Surya

Lors de l'utilisation de appliquer à un groupe, j'ai rencontré que .apply renverrait les colonnes groupées. Il y a une note dans la documentation (pandas.pydata.org/pandas-docs/stable/groupby.html):

"... Ainsi, les colonnes groupées peuvent être incluses dans la sortie et définir les index."

.aggregate ne renverra pas les colonnes groupées.

0