В чем разница между pandas agg и функцией apply?

я не могу понять разницу между пандами .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

3 ответов


apply применяет функцию к каждой группе (your Species). Ваша функция возвращает 1, поэтому вы получаете 1 значение для каждой из 3 групп.

agg Сростки каждый столбец (функция) для каждой группы, так что вы в конечном итоге с одним значением на столбец на группу.

читать groupby docs, они довольно полезны. Есть также куча учебников, плавающих по всему интернету.


( Примечание: это сравнение актуально для объектов DataframeGroupby )

каким-нибудь благовидным преимущества использования .agg () по сравнению с .apply (),для объектов GroupBy фрейма данных будет:

1) .agg () дает гибкость применение нескольких функций одновременно или передайте список функций в каждый столбец.

2) Кроме того, применение различных функций сразу к различным столбцы таблицы данных.

это означает, что вы в значительной степени контролируете каждый столбец с каждой операцией.

вот ссылка для более подробной информации: http://pandas.pydata.org/pandas-docs/version/0.13.1/groupby.html

однако функция apply может быть ограничена применением одной функции к каждому столбцу фрейма данных за раз. Таким образом, вам может потребоваться вызвать функцию apply несколько раз, чтобы вызвать различные операции к тому же колонна.

вот, некоторые примеры сравнения для .apply () vs .agg () для объектов DataframeGroupBy :

позволяет, во-первых, увидеть операции с использованием .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

Так, .agg () может быть очень удобен при обработке объектов DataFrameGroupBy по сравнению с ними .применять.) ( но, если вы обрабатываете только чистый dataframe объекты, а не объекты DataFrameGroupBy, то apply () может быть очень полезно, Так как apply () может применить функцию вдоль любой оси фрейма данных.

(например: axis = 0 подразумевает работу по столбцу .apply (),, который является режимом по умолчанию, и axis = 1 означало бы для строчной операции при работе с чистыми объектами dataframe)


при использовании применить к groupby я столкнулся с этим .apply вернет сгруппированные столбцы. В документации есть примечание (pandas.pydata.org/pandas-docs/stable/groupby.html):

"...Таким образом, сгруппированные столбцы могут быть включены в выходные данные, а также установить индексы."

.aggregate не вернет сгруппированные столбцы.