熊猫:GroupBy .pipe() 与 .apply()

Posted

技术标签:

【中文标题】熊猫:GroupBy .pipe() 与 .apply()【英文标题】:pandas: GroupBy .pipe() vs .apply() 【发布时间】:2018-04-23 21:31:24 【问题描述】:

在 pandas documentation 的示例中,关于 GroupBy 对象的新 .pipe() 方法,接受相同 lambda 的 .apply() 方法将返回相同的结果。

In [195]: import numpy as np

In [196]: n = 1000

In [197]: df = pd.DataFrame('Store': np.random.choice(['Store_1', 'Store_2'], n),
   .....:                    'Product': np.random.choice(['Product_1', 'Product_2', 'Product_3'], n),
   .....:                    'Revenue': (np.random.random(n)*50+10).round(2),
   .....:                    'Quantity': np.random.randint(1, 10, size=n))

In [199]: (df.groupby(['Store', 'Product'])
   .....:    .pipe(lambda grp: grp.Revenue.sum()/grp.Quantity.sum())
   .....:    .unstack().round(2))

Out[199]: 
Product  Product_1  Product_2  Product_3
Store                                   
Store_1       6.93       6.82       7.15
Store_2       6.69       6.64       6.77

我可以看到 pipe 功能与 apply 的 DataFrame 对象有何不同,但 GroupBy 对象却没有。有没有人解释或举例说明pipe 可以做什么,而apply 不能用于 GroupBy?

【问题讨论】:

【参考方案1】:

pipe 所做的是允许您传递可调用对象,并期望调用 pipe 的对象是传递给可调用对象的对象。

对于apply,我们假设调用apply 的对象具有子组件,每个子组件将传递给传递给apply 的可调用对象。在groupby 的上下文中,子组件是调用groupby 的数据帧的切片,其中每个切片本身就是一个数据帧。这与groupby 系列类似。

您可以在groupby 上下文中使用pipe 所做的主要区别在于,您可以在groupby 对象的整个范围内使用可调用对象。对于申请,你只知道本地切片。

设置 考虑df

df = pd.DataFrame(dict(
    A=list('XXXXYYYYYY'),
    B=range(10)
))

   A  B
0  X  0
1  X  1
2  X  2
3  X  3
4  Y  4
5  Y  5
6  Y  6
7  Y  7
8  Y  8
9  Y  9

示例 1 使整个'B' 列总和为1,而每个子组的总和为相同的数量。这要求计算知道存在多少组。这是我们无法用 apply 做的事情,因为 apply 不知道存在多少组。

s = df.groupby('A').B.pipe(lambda g: df.B / g.transform('sum') / g.ngroups)
s

0    0.000000
1    0.083333
2    0.166667
3    0.250000
4    0.051282
5    0.064103
6    0.076923
7    0.089744
8    0.102564
9    0.115385
Name: B, dtype: float64

注意:

s.sum()

0.99999999999999989

还有:

s.groupby(df.A).sum()

A
X    0.5
Y    0.5
Name: B, dtype: float64

示例 2 从另一组的值中减去一组的平均值。同样,apply 无法做到这一点,因为 apply 不知道其他组。

df.groupby('A').B.pipe(
    lambda g: (
        g.get_group('X') - g.get_group('Y').mean()
    ).append(
        g.get_group('Y') - g.get_group('X').mean()
    )
)

0   -6.5
1   -5.5
2   -4.5
3   -3.5
4    2.5
5    3.5
6    4.5
7    5.5
8    6.5
9    7.5
Name: B, dtype: float64

【讨论】:

以上是关于熊猫:GroupBy .pipe() 与 .apply()的主要内容,如果未能解决你的问题,请参考以下文章

熊猫与 groupby 滚动最大

与 groupby 的熊猫数据帧总和

GroupBy 每周在熊猫中与其他列一起计数

熊猫:Groupby,循环并添加一小时迭代与组内的条件

熊猫:在 groupby 'date' 中删除重复项

如何计算满足特定条件的熊猫 groupby 的值