NumPy中如何按首列相同值对第二列分组求和并保留原顺序?
NumPy 有序分组求和最佳实践
NumPy 核心库没有提供一步完成该需求的专用API,但依托基础向量化API可以实现零Python层循环的高性能方案,完全符合NumPy设计理念,性能远高于逐行遍历写法。
由于你的输入已经按第一列完成排序,相同取值的行连续排列,这是最高效的处理前提,不需要额外排序开销。
实现代码
import numpy as np # 假设arr是你的输入数组 col1, col2 = arr[:, 0], arr[:, 1] # 定位每个连续相同值分组的起始索引 group_starts = np.where(np.diff(col1, prepend=np.array([np.nan])) != 0)[0] # 提取每个分组的唯一第一列值,对第二列按分组合计 res_col1 = col1[group_starts] res_col2 = np.add.reduceat(col2, group_starts) # 拼接为最终结果 result = np.column_stack((res_col1, res_col2))
用你给出的样例输入运行,输出和预期完全一致:
array([[ 113.555 , 1506. ], [ 113.595 , 1460. ], [ 113.605 , 6902. ], [ 113.612 , 3434. ], [ 113.6351, 2095. ]])
方案说明
- 所有操作均为NumPy底层C实现的向量化运算,没有Python层面的逐行遍历,数据量越大性能优势越明显,十万级以上数据比手写循环快百倍以上。
- 分组定位完全按原数组顺序提取,天然保留原有排列顺序,不需要额外排序操作。
- 内存开销极低,不需要构造和原数组等长的分组标签数组。
注意事项
- 该方案依赖「同值行连续排列」的前提,你的输入已经按第一列排序,完全满足要求。如果处理无序数组,需要先执行
arr = arr[np.argsort(arr[:,0])]排序后再使用。 - 如果第一列是浮点数,存在计算精度导致的同值判断误差,可以将分组定位的判断逻辑改为阈值判断,比如:
阈值group_starts = np.where(np.abs(np.diff(col1, prepend=np.array([np.nan]))) > 1e-8)[0]1e-8可以根据你的数据精度要求调整。
如果需要更丰富的分组聚合功能,可以使用第三方库numpy_groupies,但纯NumPy环境下上述实现就是该场景的标准最优写法。
内容的提问来源于stack exchange,提问作者M.E.
相关产品推荐
相关产品推荐

