В чем разница между функцией pandas agg и apply?
Я не могу понять разницу между .aggregate
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
Ответы
Ответ 1
apply
применяет функцию к каждой группе (ваши Species
). Ваша функция возвращает 1, поэтому вы получаете 1 значение для каждой из 3 групп.
agg
объединяет каждый столбец (функцию) для каждой группы, поэтому вы agg
одно значение для каждого столбца на группу.
groupby
документы groupby
, они очень полезны. Есть также куча учебников, плавающих вокруг Интернета.
Ответ 2
(Примечание. Эти сравнения актуальны для объектов DataframeGroupby)
Некоторые вероятные преимущества использования .agg()
по сравнению с .apply()
, для объектов DataFrame GroupBy :
.agg()
обеспечивает гибкость одновременного применения нескольких функций или передачи списка функций в каждый столбец.
Кроме того, одновременно применяя разные функции к различным столбцам информационного кадра.
Это означает, что вы можете контролировать каждый столбец с каждой операцией.
Вот ссылка для более подробной информации: http://pandas.pydata.org/pandas-docs/version/0.13.1/groupby.html
Однако функция apply
может быть ограничена применением одной функции к каждому столбцу кадра данных за раз. Поэтому вам, возможно, придется несколько раз вызывать функцию apply для вызова различных операций в одном и том же столбце.
Вот несколько примеров сравнений для .apply()
и .agg()
для объектов DataframeGroupBy:
С учетом следующего кадра данных:
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
Давайте сначала посмотрим на операции, используя .apply()
:
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 [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 по сравнению с .apply()
. Но если вы обрабатываете только чистые объекты фрейма данных, а не объекты DataFrameGroupBy, то apply()
может быть очень полезным, так как apply()
может применять функцию вдоль любой оси фрейма данных.
(Например, axis = 0
подразумевает посимвольную работу с .apply(),
, который является режимом по умолчанию, а axis = 1
подразумевает построчную работу при работе с объектами с чистыми данными).
Ответ 3
При использовании apply to groupby я обнаружил, что .apply
возвращает сгруппированные столбцы. В документации есть примечание (pandas.pydata.org/pandas-docs/stable/groupby.html):
"... Таким образом, сгруппированные столбцы могут быть включены в вывод, а также установить индексы."
.aggregate
не вернет сгруппированные столбцы.