我想在这里记录'split-apply-combine'方法的特殊情况。
问题:我从DataFrame开始,我必须对需要进行groupby拆分的数据进行一些处理并返回一些结果。让我们进一步假设处理不能通过简单的内置操作(有快捷方式)来完成,但是它非常复杂,我必须遍历各个组。此外,我希望将结果放回原始DataFrame中。 (是的,我知道,如果结果是整个组的单个标量,那么我将消耗大量内存。但是,通常我确实希望将那些结果存储在原始数据表中,而不是处理这些结果。另一张桌子)。
我发现在熊猫文档中和此处都没有很好地记录这种情况。
让我们举例说明:
import pandas as pd
import numpy as np
# Prepare DataFrame
data = {'Group':['A']*4+['B']*4+['C']*4,'Prop1':['S1','S2','S3','S4','S5','S6','S7','S8','S9','S10',
'S11','S12'],'Prop2':[2004,2004,3004,3004,4004,4004,5004,5004,6004,6004,7004,7004],
'Res1':[0,1,2,3,10,11,12,13,20,21,22,23]}
df = pd.DataFrame(data=data)
df
现在,我们继续进行groupby运算并计算新结果:
df['Res2'] = np.nan
df['Res3'] = np.nan
grouped = df.groupby('Group')
for (key,gr) in grouped:
# Calculate two new results based on gr values
res2 = gr['Res1'].mean()
gr['Res2'] = res2
res3 = gr['Prop2'] + gr['Res1']
gr['Res3'] = res3
# At this point gr has two new columns Res2 and Res3
# Now we need to copy those changes back to the original DataFrame df
df.update(gr)
这里最棘手的部分是将结果放回到df
中。请注意,我必须首先在df
中创建两个新列,否则将无法正常工作。第一种方法是使用.update
命令。这很容易阅读。使用%timeit
命令,我将此时间定为(1.85ms,1.84ms,1.74ms)。
执行此操作的第二种方法是注意原始索引保留在gr
中。因此我们可以将df.update(gr)
替换为:
df.loc[gr.index,('Res2','Res3')] = gr[['Res2','Res3']]
在这些单元格中的任何一个之后,我们都得到了预期的结果(以及臭名昭著的SettingWithCopy
警告):
有趣的是,第二种方法稍快一些,计时时间为(1.66ms,1.69ms,1.73ms)。
我的问题是,有没有更简单的方法? 而且,对于具有行多索引的DataFrame该如何完成?
答案 0 :(得分:1)
您可以对Res2使用变换,而Res3只是总和。无需创建两个新列
df['Res2'] = df.groupby('Group').Res1.transform('mean')
df['Res3'] = df['Prop2'] + df['Res1']
Group Prop1 Prop2 Res1 Res2 Res3
0 A S1 2004 0 1.5 2004
1 A S2 2004 1 1.5 2005
2 A S3 3004 2 1.5 3006
3 A S4 3004 3 1.5 3007
4 B S5 4004 10 11.5 4014
5 B S6 4004 11 11.5 4015
6 B S7 5004 12 11.5 5016
7 B S8 5004 13 11.5 5017
8 C S9 6004 20 21.5 6024
9 C S10 6004 21 21.5 6025
10 C S11 7004 22 21.5 7026
11 C S12 7004 23 21.5 7027