NumPy ndarray按条件替换元素时遍历修改结果异常如何解决
问题根源
你写的循环逻辑存在核心错误:np.nditer(f_vars)遍历得到的变量i是数组里的元素值,不是元素的索引。你写f_vars[i] = f_vars[i]+1相当于把遍历到的数值当下标去定位数组行,完全没有修改当前遍历到的目标元素,还会因为反复修改整行数据导致结果完全错乱。
比如第一次遍历拿到元素值0,判断0<2成立,就会执行f_vars[0] +=1,直接把第0行整行所有元素都加1;后续遍历到其他小于2的元素值时,又会反复修改对应下标的整行数据,最终就会出现你看到的错位、数值异常的结果。
正确实现方案
Numpy数组操作优先用向量化逻辑实现,比写循环效率高几个量级,还能避免循环写错索引的问题。注意所有条件判断要基于原始数组的数值做,不要边修改边判断,避免出现连锁修改的问题。
import numpy as np f_vars = np.array([[0,4], [0,2], [3,-1], [3,4], [1,-1]]) th1 = 2 # 第一个阈值 th2 = 4 # 第二个阈值 res = np.empty_like(f_vars) # 按规则逐类赋值,所有判断基于原始数组f_vars # 规则1:值为-1保持不变 res[f_vars == -1] = -1 # 规则2:小于th1且不是-1的元素,值加1 mask = (f_vars < th1) & (f_vars != -1) res[mask] = f_vars[mask] + 1 # 规则3:值等于th1的元素置0 res[f_vars == th1] = 0 # 规则4:值介于th1和th2之间的元素保持原值 mask = (f_vars > th1) & (f_vars < th2) res[mask] = f_vars[mask] # 规则5:值等于th2的元素置0 res[f_vars == th2] = 0 # 规则6:值大于th2的元素值减1 mask = f_vars > th2 res[mask] = f_vars[mask] - 1 print(res)
运行后输出符合预期的结果:
[[ 1 0] [ 1 0] [ 3 -1] [ 3 0] [ 2 -1]]
如果你一定要用循环实现,需要用能拿到元素索引的遍历方式,不要把元素值当索引用,参考写法如下(不推荐,大数据量下效率极低):
th1 = 2 th2 = 4 # 同时拿到索引和对应的值 for idx, val in np.ndenumerate(f_vars): if val == -1: continue elif val < th1: f_vars[idx] = val + 1 elif val == th1: f_vars[idx] = 0 elif th1 < val < th2: continue elif val == th2: f_vars[idx] = 0 elif val > th2: f_vars[idx] = val - 1
内容的提问来源于stack exchange,提问作者Petar Andreev
相关产品推荐
相关产品推荐

