如果满足条件,如何交换数组的列

时间:2018-01-12 20:15:28

标签: python arrays numpy image-processing multidimensional-array

我有一个Nx3 numpy数组:

A = [[01,02,03]
     [11,12,13]
     [21,22,23]]

如果第二个和第三个数字的总和大于20,我需要一个交换第二和第三列的数组:

[[01,02,03]
 [11,13,12]
 [21,23,22]]

是否有可能在没有循环的情况下实现这一目标?

更新

所以,这背后的故事是我想在RGB图像中交换颜色,即绿色和蓝色,但不是黄色 - 这是我的条件。根据经验,我发现它是abs(green - blue) > 15 && (blue > green)

swapped = np.array(img).reshape(img.shape[0] * img.shape[1], img.shape[2])
idx = ((np.abs(swapped[:,1] - swapped[:,2]) < 15) & (swapped[:, 2] < swapped[:, 1]))

swapped[idx, 1], swapped[idx, 2] = swapped[idx, 2], swapped[idx, 1]

plt.imshow(swapped.reshape(img.shape[0], img.shape[1], img.shape[2]))

这实际上有效,但部分有效。第一列将被交换,但第二列将被覆盖。

# tested in pyton3
a = np.array([[1,2,3],[11,12,13],[21,22,23]])
a[:,1], a[:,2] = a[:,2], a[:,1]

array([[ 1,  3,  3],
       [11, 13, 13],
       [21, 23, 23]])

2 个答案:

答案 0 :(得分:3)

这是masking -

的一种方式
# Get 1D mask of length same as the column length of array and with True
# values at places where the combined sum is > 20
m = A[:,1] + A[:,2] > 20

# Get the masked elements off the second column
tmp = A[m,2]

# Assign into the masked places in the third col from the
# corresponding masked places in second col.
# Note that this won't change `tmp` because `tmp` isn't a view into
# the third col, but holds a separate memory space
A[m,2] = A[m,1]

# Finally assign into the second col from tmp
A[m,1] = tmp

示例运行 -

In [538]: A
Out[538]: 
array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23]])

In [539]: m = A[:,1] + A[:,2] > 20
     ...: tmp = A[m,2]
     ...: A[m,2] = A[m,1]
     ...: A[m,1] = tmp

In [540]: A
Out[540]: 
array([[ 1,  2,  3],
       [11, 13, 12],
       [21, 23, 22]])

答案 1 :(得分:2)

如何使用np.where以及&#34; fancy&#34;索引,并np.flip交换元素。

In [145]: A
Out[145]: 
array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23]])

# extract matching sub-array
In [146]: matches = A[np.where(np.sum(A[:, 1:], axis=1) > 20)]

In [147]: matches
Out[147]: 
array([[11, 12, 13],
       [21, 22, 23]])

# swap elements and update the original array using "boolean" indexing
In [148]: A[np.where(np.sum(A[:, 1:], axis=1) > 20)] = np.hstack((matches[:, :1], np.flip(matches[:, 1:], axis=1)))

In [149]: A
Out[149]: 
array([[ 1,  2,  3],
       [11, 13, 12],
       [21, 23, 22]])

基于@Divakar's suggestion的另一种方法是:

首先获取指定条件的非零指数(此处为  <第二列和第三列中的元素的总和> 20)

In [70]: idx = np.flatnonzero(np.sum(A[:, 1:3], axis=1) > 20)

然后使用np.ix_

创建一个开放网格
In [71]: gidx = np.ix_(idx,[1,2])

# finally update the original array `A`
In [72]: A[gidx] = A[gidx][:,::-1]