pandas:GroupBy .pipe()vs .apply()

fog*_*rit 14 python python-3.x pandas pandas-groupby

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

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
Run Code Online (Sandbox Code Playgroud)

我可以看到pipe功能与applyDataFrame对象的不同之处,但不适用于GroupBy对象.有没有人对GroupBy 有什么解释或示例,pipe但没有apply

piR*_*red 27

是什么pipe让你传递一个callable,期望被调用pipe的对象是传递给callable的对象.

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

pipegroupby上下文中可以执行的操作之间的主要区别在于您可以调用groupby对象的整个范围.对于apply,您只知道本地切片.

设置
考虑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
Run Code Online (Sandbox Code Playgroud)

示例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
Run Code Online (Sandbox Code Playgroud)

注意:

s.sum()

0.99999999999999989
Run Code Online (Sandbox Code Playgroud)

和:

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

A
X    0.5
Y    0.5
Name: B, dtype: float64
Run Code Online (Sandbox Code Playgroud)

示例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
Run Code Online (Sandbox Code Playgroud)