如何避免循环实现Numpy数组按索引映射的批量求和操作?
高效解决Numpy数组按映射分组求和问题
核心思路
用Numpy的np.bincount实现向量化分组求和,彻底替代Python循环,适配十万级甚至更大规模的数组运算。bincount能根据给定索引数组,对权重数组元素做分组累加,完美匹配需求场景。
实现步骤
- 展开映射关系:把字典
m的键值对转换成两个一维数组:arr2_indices:展开所有arr2的索引(将字典值列表逐个展开)arr1_indices:每个arr2索引对应的arr1索引(按对应次数重复字典的键)
- 调用
np.bincount计算:以arr1_indices为分组依据,arr2[arr2_indices]为待求和权重,直接得到arr1的结果。
代码示例
import numpy as np # 示例数据 m = { 0: [0,1], 1: [1,2], 2: [3,4], } arr2 = np.array([1,5,7,9,12]) M = len(m) # arr1的长度 # 展开映射关系 arr1_indices = [] arr2_indices = [] for idx1, idxs2 in m.items(): arr1_indices.extend([idx1]*len(idxs2)) arr2_indices.extend(idxs2) # 转为Numpy数组 arr1_indices = np.array(arr1_indices) arr2_indices = np.array(arr2_indices) # 计算分组求和 arr1 = np.bincount(arr1_indices, weights=arr2[arr2_indices], minlength=M) print(arr1) # 输出: [ 6 12 21]
性能优势
np.bincount是C实现的向量化操作,比Python循环快数个数量级。十万级规模下,仅需一次轻量的映射展开(开销远低于循环),后续计算全由Numpy处理,彻底规避Python解释器的循环开销。
扩展适配其他聚合操作
如果需要执行求和之外的聚合逻辑,可结合Numpy其他函数实现:
- 求均值:先通过
bincount求和,再除以每个分组的元素个数(分组个数用np.bincount(arr1_indices)获取) - 求最大值:用
np.maximum.at做原地向量化更新:arr1_max = np.zeros(M) np.maximum.at(arr1_max, arr1_indices, arr2[arr2_indices]) print(arr1_max) # 输出: [ 5. 7. 12.]
内容的提问来源于stack exchange,提问作者Ftagliacarne
相关产品推荐
相关产品推荐

