В чем разница между 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 не вернет сгруппированные столбцы.