如何在Numpy中高效实现预定义区间内的元素赋值操作?
实现方案
1. 单行向量化实现
直接通过numpy广播和逻辑运算合并即可实现单行生成目标Mask,不需要显式写Python层面的循环:
Mask = np.logical_or.reduce((np.arange(11) >= b_top[:, None]) & (np.arange(11) < b_low[:, None]), axis=0)[np.newaxis, :]
原理是把每个区间的起止值和全局索引做广播比较,得到每个区间对应的布尔数组,再按维度合并所有区间的布尔结果,最终扩展出第一个维度得到和原代码结构一致的Mask。
2. 更高性能的实现(适合区间数量大、数组长度长的场景)
如果你的区间数量非常多,上面的广播方法会占用较多内存,这时候用标记累积法性能更高,时间复杂度为O(数组长度 + 区间数量):
marker = np.zeros(11 + 1, dtype=np.int8) np.add.at(marker, b_top, 1) np.add.at(marker, b_low, -1) Mask = (marker.cumsum()[:-1] > 0)[np.newaxis, :]
原理是在每个区间的起始位置标记+1,结束位置标记-1,做前缀和之后大于0的位置就是落在至少一个区间内的位置,直接转布尔值即可得到目标Mask。
原写法的Python层面循环在区间数量很少的时候性能差异不大,但区间数量超过100之后,上述两种向量化实现的性能优势会非常明显。
内容的提问来源于stack exchange,提问作者rpb
相关产品推荐
相关产品推荐

