Python 使用groupby->;在多个列上执行函数时,在数据帧上执行转换(func),优先考虑速度

Python 使用groupby->;在多个列上执行函数时,在数据帧上执行转换(func),优先考虑速度,python,pandas,dataframe,join,pandas-groupby,Python,Pandas,Dataframe,Join,Pandas Groupby,假设我有一个数据帧: df= pd.DataFrame({'grouping_col':['B','B','S','S','S','B'],'column1':[10,20,30,40,50,60],'column2':[5,6,7,8,9,10],'column3':[11,12,13,14,15,16],'column4':[16,17,18,19,20,21]}) df.set_index('grouping_col',inplace= True) 假设我有一个函数 def func(

假设我有一个数据帧:

df= pd.DataFrame({'grouping_col':['B','B','S','S','S','B'],'column1':[10,20,30,40,50,60],'column2':[5,6,7,8,9,10],'column3':[11,12,13,14,15,16],'column4':[16,17,18,19,20,21]})

df.set_index('grouping_col',inplace= True)
假设我有一个函数

def func(x,col1,col2,col3,col4):
    return sum(x[col1]**2 * x[col2] * x[col3] * x[col4]) / sum(x[col1]**2 *x[col3]**2 * x[col4]**2)
我试图在数据帧上使用GROUPBY,然后应用该函数。有效的方法是:

new_col= df.groupby('grouping_col').apply(func,'column1','column2','column3','column4').rename('new_col_name')
df = df.join(new_col,how= 'left')
print(df)

              column1  column2  column3  column4  new_col_name
grouping_col                                                  
B                  10        5       11       16      0.029738
B                  20        6       12       17      0.029738
B                  60       10       16       21      0.029738
S                  30        7       13       18      0.030011
S                  40        8       14       19      0.030011
S                  50        9       15       20      0.030011
这很好,但我需要在更大/更复杂的数据帧上应用此函数数千次,并且连接需要花费不合理的长时间,因此我尝试提出一种更快的方法

到目前为止,我已经尝试:

df['new_col_name'] = df.groupby('grouping_col').transform(lambda x: func(x,'column1','column2','column3','column4'))

result: KeyError: ('column1', 'occurred at index column1')

所以我猜它不起作用,因为转换分别对每一列进行操作。有谁有更好的主意吗?提前谢谢

一个可能的想法是在使用groupby之前计算数学运算的分子
n
和分母
d
,然后使用对数据帧索引上的分子和分母进行分组,最后使用
sum
转换分子和分母

n = df['column1']**2 * df['column2'] * df['column3'] * df['column4']
d = df['column1']**2 * df['column3']**2 * df['column4']**2

df['new_col_name'] = (
    n.groupby(df.index).transform('sum') /
    d.groupby(df.index).transform('sum')
)
或者

结果:

# print(df)
              column1  column2  column3  column4  new_col_name
grouping_col                                                  
B                  10        5       11       16      0.029738
B                  20        6       12       17      0.029738
S                  30        7       13       18      0.030011
S                  40        8       14       19      0.030011
S                  50        9       15       20      0.030011
B                  60       10       16       21      0.029738

这真是好东西。最后一个问题:有没有办法只使用一个groupby?@Vincent_Adultman你可以,但我认为在性能方面没有任何明显的改进。如果你愿意,我可以给你看……是的,如果你不介意的话,我有点好奇。不管怎样,我都会把你的答案标为正确。
# print(df)
              column1  column2  column3  column4  new_col_name
grouping_col                                                  
B                  10        5       11       16      0.029738
B                  20        6       12       17      0.029738
S                  30        7       13       18      0.030011
S                  40        8       14       19      0.030011
S                  50        9       15       20      0.030011
B                  60       10       16       21      0.029738