问题:如何按照指定条件去对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之四:高级索引和索引技巧