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,如果每个组中只有一个columnagg 是更好的选择。 【参考方案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:函数不减少”

pandas agg函数使用方法

groupby+(apply+agg+transform)方法的比较

pandas中apply和transform方法的性能比较

pandas新字段(数据列)生成使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战