pandas 如何在多个列之间使用groupby转换

83qze16e  于 2022-11-27  发布在  其他
关注(0)|答案(3)|浏览(151)

我有一个很大的 Dataframe ,我按1到n列分组,并希望在这些组上跨两列应用一个函数(例如foo和bar)。
下面是一个 Dataframe 示例:

foo_function = lambda x: np.sum(x.a+x.b)

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']})

# works with apply, but I want transform:
df.groupby(['c', 'd'])[['a','b']].apply(foo_function)
# transform doesn't work!
df.groupby(['c', 'd'])[['a','b']].transform(foo_function)
TypeError: cannot concatenate a non-NDFrame object

但是transform显然不能将多个列组合在一起,因为它分别查看每个列(与apply不同)。就速度/优雅性而言,下一个最佳选择是什么?例如,我可以使用apply,然后使用pd.match创建df['new_col'],但这有时需要在多个groupby列(col 1和col 2)上进行匹配,这看起来确实很麻烦/需要相当多的代码。
--〉是否有类似groupby().transform的函数可以使用多列函数?如果不存在,最好的办法是什么?

mnemlml8

mnemlml81#

Circa Pandas 0.18版,看来原来的答案(下图)不再起作用。
相反,如果需要跨多列执行groupby计算,请 * 首先 * 执行多列计算,然后执行groupby:

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']})
df['e'] = df['a'] + df['b']
df['e'] = (df.groupby(['c', 'd'])['e'].transform('sum'))
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

原文回答:
错误消息:

TypeError: cannot concatenate a non-NDFrame object

建议foo_function应返回NDFrame(如Series或DataFrame)以便进行连接。如果返回Series,则:

In [99]: df.groupby(['c', 'd']).transform(lambda x: pd.Series(np.sum(x['a']+x['b'])))
Out[99]: 
    a   b
0  12  12
1  12  12
2  12  12
3   8   8
4  22  22
5  22  22
aamkag61

aamkag612#

我对这个问题的理解是,您希望能够对两个列中的单个值执行任意操作。您只需要确保返回的 Dataframe 与传入的 Dataframe 大小相同。我认为最好的方法是创建一个新列,如下所示:

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']})
df['e']=0

def f(x):
    y=(x['a']+x['b'])/sum(x['b'])
    return pd.DataFrame({'e':y,'a':x['a'],'b':x['b']})

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

a   b   e
0   1   1   0.333333
1   2   2   0.666667
2   3   3   1.000000
3   4   4   2.000000
4   5   5   0.909091
5   6   6   1.090909

如果您有一个非常复杂的 Dataframe ,您可以选择您的列(例如df.groupby(['c'])['a','b','e'].transform(f)
在我看来,这确实很不优雅,但在大型数据集上,它仍然比apply快得多。
另一种方法是使用set_index捕获所需的所有列,然后只将一列传递给transform

uqcuzwp8

uqcuzwp83#

以下解决方法允许您使用类似的transform语法进行转换,但改用.groupby.apply
因此,您不必将多列计算分开,从而使处理步骤变得支离破碎。
第一个

相关问题