Pandas groupby + transform和多列

10
为了获得与原始DataFrame相同细节级别(相同的观察计数)的groupby数据执行结果,我使用了transform函数。
示例: 原始数据框
name, year, grade
Jack, 2010, 6
Jack, 2011, 7
Rosie, 2010, 7
Rosie, 2011, 8

进行了groupby之后的转换结果

name, year, grade, average grade
Jack, 2010, 6, 6.5
Jack, 2011, 7, 6.5
Rosie, 2010, 7, 7.5
Rosie, 2011, 8, 7.5

然而,基于多列的更高级功能会使事情变得更加复杂。让我困惑的是,在groupby-transform组合中,似乎无法访问多个列。

df = pd.DataFrame({'a':[1,2,3,4,5,6],
               'b':[1,2,3,4,5,6],
               'c':['q', 'q', 'q', 'q', 'w', 'w'],  
               'd':['z','z','z','o','o','o']})

def f(x):
 y=sum(x['a'])+sum(x['b'])
 return(y)

df['e'] = df.groupby(['c','d']).transform(f)

给我:

KeyError: ('a', 'occurred at index a')

尽管我知道以下内容是有效的:

df.groupby(['c','d']).apply(f)

什么导致这种行为,我如何获取类似的东西:
a   b   c   d   e
1   1   q   z   12
2   2   q   z   12
3   3   q   z   12
4   4   q   o   8
5   5   w   o   22
6   6   w   o   22

看一下这个答案,它可能会帮助你理解为什么。 - Ben.T
我注意到在函数f中使用print(x)时,列变成了标量。但是我该如何克服这个问题? - Willem
2个回答

13

对于这个特定情况,你可以这样做:

g = df.groupby(['c', 'd'])

df['e'] = g.a.transform('sum') + g.b.transform('sum')

df
# outputs

   a  b  c  d   e
0  1  1  q  z  12
1  2  2  q  z  12
2  3  3  q  z  12
3  4  4  q  o   8
4  5  5  w  o  22
5  6  6  w  o  22

如果您可以通过对同一分组应用独立的变换来构建最终结果的线性组合,则此方法可行。

否则,您将使用 groupby-apply ,然后合并回原始数据框。

示例:

_ = df.groupby(['c','d']).apply(lambda x: sum(x.a+x.b)).rename('e').reset_index()
df.merge(_, on=['c','d'])
# same output as above.

刚刚意识到我已经发布了一个完全相同的替代方案,使用了合并 :) - yatu
由于某种原因,重命名导致items = [func(x) for x in index] TypeError: 'str' object is not callable。 - Willem
通常情况下,您应该避免在Pandas系列/NumPy数组中使用内置函数。实际上,使用字符串“'sum'”而不是sum会被Pandas路由到一个经过验证的方法,您应该能够依赖它。 - jpp
为什么要使用.reset_index()?难道使用索引的merge不更快吗?而且索引可以保证正确的行顺序(一些应用操作会改变组内的顺序)。 - william_grisaitis

2
您可以使用GroupBy + transform两次与sum一起使用:
df['e'] = df.groupby(['c', 'd'])[['a', 'b']].transform('sum').sum(1)

print(df)

   a  b  c  d   e
0  1  1  q  z  12
1  2  2  q  z  12
2  3  3  q  z  12
3  4  4  q  o   8
4  5  5  w  o  22
5  6  6  w  o  22

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接