考虑以下数据帧:
A B C D
0 foo one 0.162003 0.087469
1 bar one -1.156319 -1.526272
2 foo two 0.833892 -1.666304
3 bar three -2.026673 -0.322057
4 foo two 0.411452 -0.954371
5 bar two 0.765878 -0.095968
6 foo one -0.654890 0.678091
7 foo three -1.789842 -1.130922
以下命令起作用:
> df.groupby('A').apply(lambda x: (x['C'] - x['D']))
> df.groupby('A').apply(lambda x: (x['C'] - x['D']).mean())
但以下任何一项均无效:
> df.groupby('A').transform(lambda x: (x['C'] - x['D']))
ValueError: could not broadcast input array from shape (5) into shape (5,3)
> df.groupby('A').transform(lambda x: (x['C'] - x['D']).mean())
TypeError: cannot concatenate a non-NDFrame object
为什么? 文档上的示例似乎建议通过调用transform
组,可以进行行操作处理:
# Note that the following suggests row-wise operation (x.mean is the column mean)
zscore = lambda x: (x - x.mean()) / x.std()
transformed = ts.groupby(key).transform(zscore)
换句话说,我认为转换本质上是一种特定的应用类型(不聚合)。我哪里错了?
供参考,以下是上面原始数据帧的构造:
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C' : randn(8), 'D' : randn(8)})
zscore
),则会transform
收到一个lambda函数,该函数假定每个x
都是内的一个项目group
,并且还为组中的每个项目返回一个值。我想念什么?
apply
传递整个df,但transform
将每个列作为Series分别传递。2)apply
可以返回任何形状输出(标量/系列/数据框架/数组/列表...),而transform
必须返回与组长度相同的序列(一维系列/数组/列表)。这就是为什么OP需要apply()
不transform()
。这是一个很好的问题,因为文档没有明确解释这两种差异。(类似于apply/map/applymap
或其他事物之间的区别...)
transform
必须返回数字,行或与参数相同的形状。如果是数字,则将数字设置为组中的所有元素;如果是行,则将其广播到组中的所有行。在您的代码中,lambda函数返回一列,该列无法广播到该组。