如何高效遍历pandas DataFrame并计算条件子集聚合值
问题背景
现有包含如下字段的DataFrame:
var1:取值范围为1~100var2:取值范围为1~100var3:取值范围为1~100flag:取值为0或1,用于标识事件的发生结果
需求为生成结果列表:针对var1、var2、var3在1~99区间内的所有阈值组合,分别筛选出三个字段值均大于等于对应阈值的数据子集,计算子集内事件发生总次数(对应列求和)。
当前通过三层嵌套for循环实现该逻辑,但执行效率极低,需要更快速的实现方案,原有实现代码如下:
sum_list = [] for i in range(1,100,1): for j in range(1,100,1): for k in range(1,100,1): df_temp = df[(df['var1'] >= i) & (df['var2'] >= j) & (df['var3'] >= k)] sum_list.append(df_temp['total'].sum())
优化实现
原方案慢的核心原因是999999=970299次循环每次都要全表扫描做布尔筛选、重复求和,存在巨量冗余计算。用三维后缀和的方案可以把时间复杂度从O(N*99³)降到O(N + 100³),性能提升可达数百到数千倍,且输出结果和原逻辑完全一致。
实现逻辑:
- 由于三个字段取值都是1100的整数,先统计每个`(var1,var2,var3)`取值组合对应的目标列总和,填充到101*101*101的三维数组中(索引1100对应字段取值,预留位置避免计算越界)
- 从大到小遍历三个维度,逐维度做累积和计算,直接得到所有
var1>=i、var2>=j、var3>=k组合的总和值 - 按原循环的i、j、k遍历顺序把三维数组切片展平,直接得到和原输出顺序一致的结果列表
完整代码:
import numpy as np # 初始化三维计数数组,索引0废弃不用,1~100对应字段取值 sum_arr = np.zeros((101, 101, 101), dtype=np.int64) # 单次分组聚合统计所有取值组合的目标列总和,替换total为flag即可统计flag总和 grouped = df.groupby(['var1', 'var2', 'var3'])['total'].sum() for (v1, v2, v3), val in grouped.items(): sum_arr[v1, v2, v3] = val # 计算三维后缀和,三个维度分别从高到低做累积 for i in range(99, 0, -1): sum_arr[i, :, :] += sum_arr[i+1, :, :] for j in range(99, 0, -1): sum_arr[:, j, :] += sum_arr[:, j+1, :] for k in range(99, 0, -1): sum_arr[:, :, k] += sum_arr[:, :, k+1] # 按原循环顺序展平得到结果 sum_list = sum_arr[1:100, 1:100, 1:100].flatten().tolist()
性能参考:如果原始DataFrame为10万行量级,原循环实现通常需要数十秒到数分钟,该优化方案总耗时通常在100毫秒以内。
内容的提问来源于stack exchange,提问作者Sheems
相关产品推荐
相关产品推荐

