pandas agg 和 apply 函数有啥区别?
Posted
技术标签:
【中文标题】pandas agg 和 apply 函数有啥区别?【英文标题】:What is the difference between pandas agg and apply function?pandas agg 和 apply 函数有什么区别? 【发布时间】:2014-03-16 17:00:38 【问题描述】:我无法弄清楚 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
【问题讨论】:
尝试输入help(by_species.agg)
,然后输入help(by_species.apply)
,看看它说了什么。
【参考方案1】:
apply
将该函数应用于每个组(您的Species
)。您的函数返回 1,因此您最终会为 3 个组中的每个组返回 1 个值。
agg
为每个组聚合每一列(特征),因此最终每组每列都有一个值。
请阅读groupby
文档,它们很有帮助。网上也有很多教程。
【讨论】:
因此,如果我想在整个组中使用我的func
,我应该选择apply
,如果每个组中只有一个column
,agg
是更好的选择。
【参考方案2】:
(注意:这些比较与 DataframeGroupby 对象相关)
与.apply()
相比,使用.agg()
的一些看似合理的优势,对于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
因此,与.apply()
相比,.agg()
在处理 DataFrameGroupBy 对象方面可能非常方便。 但是,如果您只处理纯数据框对象而不是 DataFrameGroupBy 对象,那么apply()
可能非常有用,因为apply()
可以沿数据框的任何轴应用函数。
(例如:axis = 0
表示按列操作,.apply(),
是默认模式,axis = 1
表示在处理纯操作时按行操作数据框对象)。
【讨论】:
另外,如果你需要一个函数来一次访问多个列,你可以使用 apply 请注意agg()
也允许您选择轴。 OP 可能意味着apply()
在选择一个或多个轴时提供更多的灵活性和控制。【参考方案3】:
apply和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'])
【讨论】:
【参考方案4】:当使用 apply 到 groupby 时,我遇到 .apply
将返回分组列。文档中有注释(pandas.pydata.org/pandas-docs/stable/groupby.html):
“...因此,分组列可以包含在输出中并设置索引。”
.aggregate
不会返回分组的列。
【讨论】:
以上是关于pandas agg 和 apply 函数有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
Pandas Series.apply() 和 Series.map() 有啥区别? [复制]
Pandas`agc`列表,“AttributeError / ValueError:函数不减少”
groupby+(apply+agg+transform)方法的比较
pandas新字段(数据列)生成使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战