【问题标题】:How to swap array's columns if condition is satisfied如果满足条件,如何交换数组的列
【发布时间】:2018-06-22 08:05:58
【问题描述】:

我有一个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]])

【问题讨论】:

  • 贴出您尝试用来解决此问题的代码。
  • 你的预期输出是什么?
  • 我已经更新了问题

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


【解决方案1】:

这是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]])

【讨论】:

  • A[m,2], A[m, 1] = A[m, 1], A[m,2]?
  • 不,我只是给你一个代码的替代方案,它使用临时变量进行交换:)(因为在 python 中,你可以在没有临时变量的情况下进行交换)。
  • 实际上我尝试了这种替代方法,但没有成功。检查我的更新。
  • @Aray 基于masking 的那个呢?你试过那个吗?
  • @JarrodRoberson 我已经更新了帖子。也许这不是一个很好的答案,但它不是一个糟糕/无用的答案,值得一票否决。我们显然有不同的标准。
【解决方案2】:

如何使用np.where 和“花式”索引以及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]

【讨论】:

  • 在尝试回答更多问题之前,请阅读How do I write a good answer?
  • 怎么样:idx = np.flatnonzero(np.sum(A[:, 1:3], axis=1) &gt; 20); gidx = np.ix_(idx,[1,2]) ; A[gidx] = A[gidx][:,::-1]?
  • @JarrodRoberson 我用更多解释更新了帖子。同样,它可能不是一流的答案,但仍然是正确的答案。 IMO,工作解决方案不应该有资格获得否决票或删除票。
猜你喜欢
  • 1970-01-01
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多