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


94

我有一个需要处理的大型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函数可以加快速度?


1
您要怎么办mask_data[y,x]==3
DSM 2013年

好一点,那仍然是一个坏像素。我将条件更改为if mask_data[y,x]>=3:
ChrisFro

Answers:


128
>>> 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
如何在不切割某些列然后再次分配回来的情况下使用特定的列实现此目的?例如,当满足条件时,仅列[2,3]中的元素应更改值,而无论条件是否满足,其他列均不会更改。
kuixiong

正确,但仅适用于零和一的情况。请参阅下面的更多一般性答复(以效率成本为单位)
博尔

89
>>> 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]])
>>>

参见,例如,用布尔数组建立索引


3
好东西,谢谢!如果要引用更改的值,可以使用a[a > 3] = -101+a[a > 3]
pexmar

1
@pexmar但是,如果您不这样做a[a > 3] = -101+a[a > 3]a[a > 3] += -101很可能会遇到内存泄漏。
塞缪尔·普雷沃斯特

1
您如何参考pexmar要求更改的值?
胡安

34

最快(和最灵活的)的方式是使用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]]

1
如果不满足条件就不想替换任何东西,那将是最好的方法?即,仅当满足条件时才替换为提供值,如果不保留原始数字,则为....
Abhishek Sengupta

1
替换小于3的a中的所有值,并保持其余值不变,请使用a[a<3] = 0
Markus Dutschke

3

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

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)
>>> 

1
是的 如果OP真的想0和1,他可以使用.astype(int)*1,但数组TrueFalse是一样好,因为它是。
DSM

-4

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.