如何在Numpy数组每行中获取出现次数最多的所有值(避免循环)
如何在Numpy数组每行中高效提取出现次数最多的元素(避免循环)
问题场景
给定形状为(x, k)的二维Numpy数组a,其中x数值极大,需要为每行收集所有出现次数最多的元素。示例如下:
- 输入数组:
a = np.asarray([[2, 7, 7, 2, 1], [1, 2, 3, 5, 5], [6, 6, 6, 6, 6]]) - 理想输出:
第一行中2和7均出现2次,并列最高频次。[[2,7], [5], [6]]
现有方案的局限
- 用循环遍历每行调用
np.unique能得到近似结果,但面对极大的x时效率极低:
输出结果:[np.array(np.unique(i, return_counts=True)) for i in a][array([[1, 2, 7],[1, 2, 2]], dtype=int64),
array([[1, 2, 3, 5], [1, 1, 1, 2]], dtype=int64),
array([[6], [5]], dtype=int64)] - 直接对多维数组使用
np.unique并指定axis=1,结果完全不符合需求:
输出结果:np.unique(a, return_counts=True, axis=1)(array([[1, 2, 2, 7, 7],
[5, 1, 5, 2, 3],
[6, 6, 6, 6, 6]]),
array([1, 1, 1, 1, 1], dtype=int64))
高效无循环解决方案
利用Numpy向量化操作结合排序、差分实现,步骤如下:
完整代码
import numpy as np a = np.asarray([[2, 7, 7, 2, 1], [1, 2, 3, 5, 5], [6, 6, 6, 6, 6]]) # 1. 对每行元素排序,让相同元素连续排列 sorted_a = np.sort(a, axis=1) # 2. 生成差分标记,定位元素变化的位置 diff = np.diff(sorted_a, axis=1, prepend=-np.inf, append=np.inf) split_indices = np.where(diff != 0)[1].reshape(a.shape[0], -1) # 3. 计算每组元素的出现次数,提取对应元素值 counts = np.diff(split_indices, axis=1) values = sorted_a[np.arange(a.shape[0])[:, None], split_indices[:, :-1]] # 4. 筛选出每行中次数等于最大值的元素 max_counts = counts.max(axis=1)[:, None] result = [row[counts[i] == max_counts[i]] for i, row in enumerate(values)] print(result) # 输出:[array([2, 7]), array([5]), array([6])]
方案说明
- 前3步完全使用Numpy向量化操作,避免逐行循环,处理大行数数据时效率远高于循环方案
- 最后一步的列表推导仅用于整理结果,仅对每行筛选后的元素打包,计算量极小,不会影响整体性能
内容的提问来源于stack exchange,提问作者ycohui
相关产品推荐
相关产品推荐

