
本文介绍一种无需显式循环、兼顾性能与可读性的方法,利用 Python 标准库 statistics.multimode 批量获取 NumPy 二维数组中每一行的众数(即出现次数最多的全部值),适用于大规模数据场景。
本文介绍一种无需显式循环、兼顾性能与可读性的方法,利用 python 标准库 `statistics.multimode` 批量获取 numpy 二维数组中每一行的众数(即出现次数最多的全部值),适用于大规模数据场景。
在科学计算和数据预处理中,常需对二维数组(如样本×特征矩阵)按行统计众数——尤其当某行存在多个并列最高频元素时(例如 [2, 7, 7, 2, 1] 中 2 和 7 均出现 2 次),传统 np.unique 配合 return_counts=True 虽能获取频次分布,但需额外逻辑筛选最大频次对应的所有值,且难以向量化到整行批量处理。
此时,Python 3.8+ 内置的 statistics.multimode 是更优解:它专为“返回所有众数”设计,行为严格符合需求——输入可迭代对象,输出按原始顺序排列的众数值列表(无重复、不排序),且天然支持多众数场景。
以下为完整实现示例:
import numpy as np
from statistics import multimode
# 示例输入:形状为 (3, 5) 的二维数组
a = np.asarray([[2, 7, 7, 2, 1],
[1, 2, 3, 5, 5],
[6, 6, 6, 6, 6]])
# 一行代码完成每行众数提取(返回 list of lists)
result = list(map(multimode, a))
print(result)
# 输出: [[2, 7], [5], [6]]✅ 优势说明:
- 零循环:map(multimode, a) 自动将 multimode 应用于 a 的每一行(NumPy 行视图为一维可迭代对象);
- 语义精准:multimode 明确定义为“返回所有出现次数最多的元素”,避免手动比对 counts 数组的繁琐逻辑;
- 内存友好:不生成中间频次表,时间复杂度接近 O(n) 每行,实测在百万行规模下仍保持高效;
- 类型安全:输入为 np.ndarray 时,multimode 自动适配其迭代行为,输出为原生 list,便于后续 NumPy 或 Pandas 集成。
⚠️ 注意事项:
- multimode 要求输入非空。若数组中存在全零行或空行,需预先过滤或捕获 StatisticsError;
- 该函数不保证输出顺序与 np.unique 一致(multimode 按首次出现顺序返回),如需升序结果,可后处理:[sorted(multimode(row)) for row in a];
- 对于超大规模数据(如行数 > 10⁷),可结合 concurrent.futures.ProcessPoolExecutor 进行进程级并行加速,但通常 map 已满足多数场景性能需求。
综上,statistics.multimode 是解决“逐行多众数提取”问题的简洁、标准、高效的首选方案——它用一行声明式代码替代了冗长的手动频次分析逻辑,在可读性、正确性与性能之间取得了优秀平衡。










