
使用 np.digitize 对数组进行向量化分段编码,无需 python 循环,可在毫秒级完成百万级元素的区间归类,是处理连续整数区间映射的最优解。
使用 np.digitize 对数组进行向量化分段编码,无需 python 循环,可在毫秒级完成百万级元素的区间归类,是处理连续整数区间映射的最优解。
在科学计算和数据预处理中,常需将一维数值数组按预设区间划分为离散类别(如:1–4→0,5–9→1,10–15→2)。若采用 Python 原生 for 循环或 np.where 多层嵌套判断,不仅代码冗长,更会因解释器开销导致性能急剧下降——尤其当数组规模达 10⁵ 以上时,耗时可能增加 10–100 倍。
推荐方案:np.digitize 向量化分箱
np.digitize 是 NumPy 内置的高效分箱函数,底层由 C 实现,专为「将数值映射到有序区间索引」而优化。其核心逻辑等价于:对每个元素 x,返回满足 bins[i-1]
针对题设条件(1~4→0, 5~9→1, 10~15→2),关键在于正确构造 bins 边界数组:
import numpy as np arr = np.array([2, 5, 10, 13, 7, 9]) # bins 定义右闭区间的分界点:[4, 9, 15] # digitize 返回:0 表示 ≤4,1 表示 >4 & ≤9,2 表示 >9 & ≤15 result = np.digitize(arr, bins=[4, 9, 15], right=True) print(result) # [0 1 2 2 1 1]
✅ 为什么最快?
- 全向量化:无 Python 循环,无布尔掩码重复广播;
- 时间复杂度 O(n log k),k 为区间数(此处 k=3,实际为 O(n));
- 内存连续访问,CPU 缓存友好;
- 比 np.searchsorted 更直观(后者需手动调整索引偏移)。
进阶用法:自定义标签与非零起始区间
若区间从非 1 开始(如 0~4, 5~9, 10~15),或需映射至任意标签(如字符串、负数),可组合 bins 起始边界与标签数组:
arr = np.array([2, 5, 10, 13, 7, 9]) bins = [0, 4, 9, 15] # 左闭右闭:[0,4], (4,9], (9,15] labels = np.array(['low', 'mid', 'high']) # digitize 返回 1/2/3 → 减1得 0/1/2 索引 mapped = labels[np.digitize(arr, bins, right=True) - 1] print(mapped) # ['low' 'mid' 'high' 'high' 'mid' 'mid']
⚠️ 注意事项
- bins 必须严格升序,否则行为未定义;
- 若 arr 中存在超出 bins 范围的值(如 bins[-1]),digitize 分别返回 0 或 len(bins),需额外处理(如 np.clip 或 np.where 过滤);
- 对浮点数同样适用,但需注意精度问题(建议配合 np.nextafter 设置容差);
- 不适用于非连续、重叠或动态区间——此时应考虑 pd.cut(Pandas)或自定义 numba.jit 加速函数。
综上,np.digitize 是处理静态、有序、左/右闭合区间映射的黄金标准:简洁、健壮、极速。在真实场景中,它常比 np.where 链快 5–20 倍,比纯 Python 循环快 3–4 个数量级。











