web-dev-qa-db-ja.com

pandas agg and apply functionの違いは何ですか?

Pandas .aggregate関数と.apply関数の違いを理解できません。
次の例を参考にしてください:データセットをロードし、groupbyを実行し、単純な関数を定義して、ユーザー.aggまたは.applyを定義します。

ご覧のとおり、関数内の印刷ステートメントは、.aggおよび.applyを使用した後も同じ出力になります。一方、結果は異なります。何故ですか?

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

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

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
33
David D

applyは、関数を各グループ(Species)に適用します。関数は1を返すため、3つのグループのそれぞれに1つの値が返されます。

agg aggregates each column(feature) for each group、つまり、最終的にグループごとの列ごとに1つの値になります。

groupby のドキュメントを読んでください。非常に役に立ちます。また、ウェブ上に浮かんでいるたくさんのチュートリアルもあります。

27
TomAugspurger

注:これらの比較はDataframeGroupbyオブジェクトに関連しています

もっともらしい。apply()と比較した.agg()の利点、DataFrame GroupByオブジェクト

1).agg()は、一度に複数の関数を適用する柔軟性を提供します、または各列に関数のリストを渡します。

2)また、データフレームの異なる列に異なる関数を一度に適用します。

つまり、各操作で各列をほぼ制御できます。

詳細については、次のリンクをご覧ください。 http://pandas.pydata.org/pandas-docs/version/0.13.1/groupby.html

ただし、関数の適用は、データフレームの各列に一度に1つの関数を適用するように制限できます。したがって、同じ列に対して異なる操作を呼び出すには、apply関数を繰り返し呼び出す必要がある場合があります。

ここに、DataframeGroupByオブジェクトの.apply()と.agg()の比較例があります:

まず、.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

次に、.agg()を使用して同じ操作を簡単に確認します:

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

そのため、.apply()と比較して、.agg()はDataFrameGroupByオブジェクトの処理に非常に便利です。しかし、純粋なデータフレームオブジェクトのみを処理し、DataFrameGroupByオブジェクトは処理しない場合、apply()はデータフレームの任意の軸に沿って関数を適用できるため、apply()は非常に役立ちます。

(例:軸= 0は、デフォルトのモードである.apply()、による列単位の演算を意味し、axis = 1は、純粋なデータフレームオブジェクトを処理する際の行単位の操作を意味します)

12
Surya

Groupbyへの適用を使用すると、.applyがグループ化された列を返すことに気づきました。ドキュメントに注記があります( pandas.pydata.org/pandas-docs/stable/groupby.html ):

"...したがって、グループ化された列は、インデックスを設定するだけでなく、出力に含めることができます。"

.aggregateはグループ化された列を返しません。

適用と集計の主な違いは次のとおりです。

apply()- 
    cannot be applied to multiple groups together 
    For apply() - We have to get_group()
    ERROR : -iris.groupby('Species').apply({'Sepal.Length':['min','max'],'Sepal.Width':['mean','min']})# It will throw error
    Work Fine:-iris.groupby('Species').get_group('Setosa').apply({'Sepal.Length':['min','max'],'Sepal.Width':['mean','min']})# It will throw error
        #because functions are applied to one data frame

agg()- 
    can be applied to multiple groups together
    For apply() - We do not have to get_group() 
    iris.groupby('Species').agg({'Sepal.Length':['min','max'],'Sepal.Width':['mean','min']})
    iris.groupby('Species').get_group('versicolor').agg({'Sepal.Length':['min','max'],'Sepal.Width':['mean','min']})        
0
Kunal