如何高效统计NumPy数组中各元素的出现次数?
高效计算NumPy数组中各元素的出现次数
对于大型NumPy数组,collections.Counter或list.count()的效率都不够理想,下面推荐两种纯NumPy的高效实现方案:
方案一:使用np.bincount(最快,限非负整数)
如果数组元素都是非负整数且数值范围不大,np.bincount是最优选择,时间复杂度为O(n),完全基于C实现,速度极快。
import numpy as np a = np.array([1, 1, 4, 10, 5, 3, 5, 5, 8, 9]) counts = np.bincount(a) result = counts[a] print(result) # 输出:array([2, 2, 1, 1, 3, 1, 3, 3, 1, 1])
原理:np.bincount会生成一个数组,其中索引对应原数组的非负整数元素,值对应该元素的出现次数。直接用原数组作为索引,即可得到每个位置元素的出现次数。
注意:如果数组包含负数、浮点数,或者元素数值范围极大(比如超过1e6),该方法会占用过多内存,不适用。
方案二:使用np.unique(通用场景)
适用于所有类型的数值数组(包括负数、浮点数),以及数值范围极大的情况,时间复杂度为O(n log n),效率远高于Python层面的方法。
import numpy as np a = np.array([1, 1, 4, 10, 5, 3, 5, 5, 8, 9]) # 获取排序后的唯一值和对应计数 values, counts = np.unique(a, return_counts=True) # 找到原数组每个元素在values中的位置 index = np.searchsorted(values, a) # 通过索引映射得到计数数组 result = counts[index] print(result) # 输出:array([2, 2, 1, 1, 3, 1, 3, 3, 1, 1])
原理:np.unique返回排序后的唯一元素数组和对应的计数数组,np.searchsorted快速定位原数组元素在唯一值数组中的位置,最后通过索引映射得到每个元素的出现次数。
为什么不推荐Counter或list.count()?
list.count():对每个元素遍历整个数组,时间复杂度O(n²),大型数组下性能极差。collections.Counter:虽然时间复杂度O(n),但需要将NumPy数组转换为Python列表,在Python层面处理,相比纯NumPy的C级操作,开销大很多,大型数组下速度差距明显。
内容的提问来源于stack exchange,提问作者Konstantin Kostanzhoglo
相关产品推荐
相关产品推荐

