我有兴趣对以下数据帧进行部分求和:
ID Name A B
1 111 foo 248 123
2 222 bar 331 94
3 111 foo 266 102
4 111 foo 217 163
5 222 bar 194 102
6 222 bar 188 89
我可以将groupby
与sum
或agg
一起使用,例如:
df = df.groupby(["ID", "Name"]).agg(sum).reset_index()
产生:
ID Name A B
1 111 foo 731 388
2 222 bar 713 285
但是,我只想合并索引,直到A列通过一些预先指定的值,然后再进行第二次分组。当该值超过预定值时,开始第三组分组,依此类推。例如,如果将阈值设置为500,则代码将产生:
ID Name A B
1 111 foo 514 225
2 222 bar 525 196
3 111 foo 217 163
4 222 bar 188 89
原始df中的行1和行3被分组。第2行和第4行进行了分组。第5行未与第1行和第3行分组,因为已超过阈值500。同样,第6行也没有分组。
行的顺序无关紧要。哪些行与其他哪些行合并无关紧要。我只需要能够使用阈值对列值进行分组。我很沮丧,特别是在尝试找出Pythonic解决方案而不是逐行遍历数据帧并显式评估每一行时。任何反馈将不胜感激。
答案 0 :(得分:2)
您可以使用自定义函数将其传递给apply函数。 首先使用cumsum标识组结尾,使用新的组ID创建一个额外的列,然后在新的中间数据帧上执行另一个groupby。
我已经将阈值作为函数的参数。
def grouper(x,threshold=500):
A = (x['A'].cumsum().values/threshold).astype(int)
loc = (np.diff(A)!=0).nonzero()[0]+1
A[loc] = A[loc]-1
x['C'] = A
return x.groupby(['C'])['A','B'].sum().reset_index(drop=True)
df.groupby(["ID", "Name"]).apply(grouper,threshold=500)