问题:如何按照指定条件去对numpy ndarray 的部分值作修改?

1、面对这个问题首先想到的是去挨个遍历数组中的每个元素:

比如对于一个二维数组:

shape = arr.shape
result = np.zeros(shape)
for x in range(0, shape[0]):
    for y in range(0, shape[1]):
        if arr[x, y] >= T:
            result[x, y] = 255

但这种方式显然无法有效的对更高维度的数组操作,而且速度很慢。如果数据维度不是很重要的话,比如只需要统计出数组中大于0的值的个数,此时可以使用ndarray.flatten函数将多维数组折叠成一维数组再做操作....

 

2、python的优点就是它的库函数丰富,numpy 提供的numpy.where()函数就可以很好地解决这一问题:

numpy.where() 有两种用法:

(1)np.where(condition, x, y)---满足条件(condition),输出x,不满足输出y。
如果是一维数组,相当于

[xv if c else yv for (c,xv,yv) in zip(condition,x,y)]
>>> aa = np.arange(10)
#函数说明:arange([start,] stop[, step,], dtype=None)根据start与stop指定的范围以及step设定的步
#长,生成一个 ndarray。比如np.arange(3)>>>array([0, 1, 2])
>>> np.where(aa,1,-1)
array([-1,  1,  1,  1,  1,  1,  1,  1,  1,  1])  # 0为False,所以第一个输出-1
>>> np.where(aa > 5,1,-1)
array([-1, -1, -1, -1, -1, -1,  1,  1,  1,  1])

>>> np.where([[True,False], [True,True]],    # 官网上的例子
             [[1,2], [3,4]],
             [[9,8], [7,6]])
array([[1, 8],
       [3, 4]])

(2) np.where(condition)

只有条件 (condition),没有x和y,则输出满足条件 (即非0) 元素的坐标 (等价于numpy.nonzero)。这里的坐标以tuple的形式给出,通常原数组有多少维,输出的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。

>>> a = np.array([2,4,6,8,10])
>>> np.where(a > 5)             # 返回索引
(array([2, 3, 4]),)   
>>> a[np.where(a > 5)]              # 等价于 a[a>5]
array([ 6,  8, 10])

>>> np.where([[0, 1], [1, 0]])
(array([0, 1]), array([1, 0]))
#[[0,1],[1,0]]的真值为两个1,各自的第一维坐标为[0,1],第二维坐标为[1,0] 

 

3、使用numpy内置索引,十分方便,而且因为numpy在算法上内部做了优化,速度也不差

ndarray:arr,则可以使用:arr[arr > 255] = x----将所有元素>255替换为值x

补充:numpy的内置索引机制:NumPy之四:高级索引和索引技巧