Numpy - 如何根据条件(或匹配模式)替换元素
我有一个numpy数组,比如说:
>>> a=np.array([[0,1,2],[4,3,6],[9,5,7],[8,9,8]])
>>> a
array([[0, 1, 2],
[4, 3, 6],
[9, 5, 7],
[8, 9, 8]])
我想把第二列和第三列的元素替换成它们两个中的最小值(逐行处理),但如果这两个元素中有一个小于3,就不替换。最终得到的数组应该是:
array([[0, 1, 2],# nothing changes since 1 and 2 are <3
[4, 3, 3], #min(3,6)=3 => 6 changed to 3
[9, 5, 5], #min(5,7)=5 => 7 changed to 5
[8, 8, 8]]) #min(9,8)=8 => 9 changed to 8
我知道可以用clip这个方法,比如说 a[:,1:3].clip(2,6,a[:,1:3])
,但是:
1) clip会对所有元素都进行处理,包括那些小于3的。
2) 我不知道怎么把clip的最小值和最大值设置成每行中这两个相关元素的最小值。
3 个回答
0
这里有一个一行代码:
a[np.where(np.sum(a,axis=1)>3),1:3]=np.min(a[np.where(np.sum(a,axis=1)>3),1:3],axis=2).reshape(1,3,1)
下面是详细解释:
>>> b = np.where(np.sum(a,axis=1)>3) # finds rows where, in a, row sums are > 3
(array([1, 2, 3]),)
>>> c = a[b,1:3] # the part of a that needs to change
array([[[3, 3],
[5, 5],
[8, 8]]])
>>> d = np.min(c,axis=2) # the minimum values in each row (cols 1 and 2)
array([[3, 5, 8]])
>>> e = d.reshape(1,3,1) # adjust shape for broadcast to a
array([[[3],
[5],
[8]]])
>>> a[np.where(np.sum(a,axis=1)>3),1:3] = e # set the values in a
>>> a
array([[0, 1, 2],
[4, 3, 3],
[9, 5, 5],
[8, 8, 8]])
1
我们首先定义了一个 row_mask
,用来表示小于3的条件,然后沿着一个轴使用 min
函数来找到 row_mask
中的最小值(也就是行中的最小值)。
这里的 newaxis
是为了让一维数组(最小值的数组)能够正确地扩展到二维的目标数组中。
a=np.array([[0,1,2],[4,3,6],[9,5,7],[8,9,8]])
row_mask = (a[:,0]>=3)
a[row_mask, 1:] = a[row_mask, 1:].min(axis=1)[...,np.newaxis]
a
=>
array([[0, 1, 2],
[4, 3, 3],
[9, 5, 5],
[8, 8, 8]])
3
只需要使用 >= 这个符号,先选择你感兴趣的内容:
b = a[:, 1:3] # select the columns
matching = numpy.all(b >= 3, axis=1) # find rows with all elements matching
b = b[matching, :] # select rows
现在你可以用下面的方法来替换掉最小的内容,比如:
# find row minimum and convert to a column vector
b[:, :] = b.min(1, keepdims=True)