如果满足条件,则替换 Numpy 元素

Posted

技术标签:

【中文标题】如果满足条件,则替换 Numpy 元素【英文标题】:Replacing Numpy elements if condition is met 【发布时间】:2013-11-15 00:21:09 【问题描述】:

我有一个大型 numpy 数组,我需要对其进行操作,以便在满足条件时将每个元素更改为 1 或 0(稍后将用作像素掩码)。数组中大约有 800 万个元素,我当前的方法对于缩减管道来说耗时太长:

for (y,x), value in numpy.ndenumerate(mask_data): 

    if mask_data[y,x]<3: #Good Pixel
        mask_data[y,x]=1
    elif mask_data[y,x]>3: #Bad Pixel
        mask_data[y,x]=0

有没有一个 numpy 函数可以加快这个速度?

【问题讨论】:

如果mask_data[y,x]==3,你想发生什么? 好点,这仍然是一个坏像素。我将条件更改为if mask_data[y,x]&gt;=3: 【参考方案1】:
>>> import numpy as np
>>> a = np.random.randint(0, 5, size=(5, 4))
>>> a
array([[4, 2, 1, 1],
       [3, 0, 1, 2],
       [2, 0, 1, 1],
       [4, 0, 2, 3],
       [0, 0, 0, 2]])
>>> b = a < 3
>>> b
array([[False,  True,  True,  True],
       [False,  True,  True,  True],
       [ True,  True,  True,  True],
       [False,  True,  True, False],
       [ True,  True,  True,  True]], dtype=bool)
>>> 
>>> c = b.astype(int)
>>> c
array([[0, 1, 1, 1],
       [0, 1, 1, 1],
       [1, 1, 1, 1],
       [0, 1, 1, 0],
       [1, 1, 1, 1]])

您可以通过以下方式缩短它:

>>> c = (a < 3).astype(int)

【讨论】:

如何在不切出某些列然后重新分配的情况下使用特定列实现这一点?例如,只有 [2, 3] 列中的元素在满足条件时才会改变值,而其他列无论是否满足条件都不会改变。 正确,但仅适用于零和一的情况。在下面查看更一般的答案(以效率为代价)【参考方案2】:
>>> a = np.random.randint(0, 5, size=(5, 4))
>>> a
array([[0, 3, 3, 2],
       [4, 1, 1, 2],
       [3, 4, 2, 4],
       [2, 4, 3, 0],
       [1, 2, 3, 4]])
>>> 
>>> a[a > 3] = -101
>>> a
array([[   0,    3,    3,    2],
       [-101,    1,    1,    2],
       [   3, -101,    2, -101],
       [   2, -101,    3,    0],
       [   1,    2,    3, -101]])
>>>

参见,例如,Indexing with boolean arrays。

【讨论】:

好东西,谢谢!如果你想引用你改变的值,你可以使用a[a &gt; 3] = -101+a[a &gt; 3] @pexmar 虽然如果你使用a[a &gt; 3] = -101+a[a &gt; 3] 而不是a[a &gt; 3] += -101,你很可能会面临内存泄漏。 您如何引用 pexmar 要求更改的值??【参考方案3】:

最快(也是最灵活)的方法是使用np.where,它根据掩码(真假值数组)在两个数组之间进行选择:

import numpy as np
a = np.random.randint(0, 5, size=(5, 4))
b = np.where(a<3,0,1)
print('a:',a)
print()
print('b:',b)

这将产生:

a: [[1 4 0 1]
 [1 3 2 4]
 [1 0 2 1]
 [3 1 0 0]
 [1 4 0 1]]

b: [[0 1 0 0]
 [0 1 0 1]
 [0 0 0 0]
 [1 0 0 0]
 [0 1 0 0]]

【讨论】:

如果不满足条件我不想用任何东西替换,那么最好的方法是什么?即仅在满足条件时替换为提供的值,如果不保留原始数字,则保持原样.... 要替换 a 中小于 3 的所有值并保持其余部分不变,请使用 a[a&lt;3] = 0【参考方案4】:

您可以像这样一步创建您的掩码数组

mask_data = input_mask_data < 3

这将创建一个布尔数组,然后可以将其用作像素掩码。请注意,我们没有更改输入数组(如您的代码中所示),而是创建了一个新数组来保存掩码数据 - 我建议这样做。

>>> input_mask_data = np.random.randint(0, 5, (3, 4))
>>> input_mask_data
array([[1, 3, 4, 0],
       [4, 1, 2, 2],
       [1, 2, 3, 0]])
>>> mask_data = input_mask_data < 3
>>> mask_data
array([[ True, False, False,  True],
       [False,  True,  True,  True],
       [ True,  True, False,  True]], dtype=bool)
>>> 

【讨论】:

是的。如果 OP 真的想要 0 和 1,他可以使用 .astype(int)*1,但 TrueFalse 的数组也一样好。【参考方案5】:

我不确定我是否理解你的问题,但如果你写:

mask_data[:3, :3] = 1
mask_data[3:, 3:] = 0

这将使所有 x 和 y 索引小于 3 的掩码数据值等于 1,其余所有值都等于 0

【讨论】:

以上是关于如果满足条件,则替换 Numpy 元素的主要内容,如果未能解决你的问题,请参考以下文章

如果条件不满足,则保留最后一个值的 if/elif/else 的 Numpy 等效项

如果满足条件,则样式元素,AngularJS

用于计算满足条件的元素数量的 Numpy 掩码

some()方法:检测数组中的元素是否满足指定条件

如果条件满足,则递减数组并打印一个值

FirstOrDefaultAsync()SingleOrDefaultAsync()方法的区别