Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用掩码仅替换numpy数组的零_Python_Numpy - Fatal编程技术网

Python 如何使用掩码仅替换numpy数组的零

Python 如何使用掩码仅替换numpy数组的零,python,numpy,Python,Numpy,考虑二维阵列: arr = np.zeros((10,10)) arr[3:7,3:7] = 1 现在,我想使用掩码将其中的一部分替换为其他值: mask = np.ones((5,5)).astype(bool) arr[5:,5:][mask] = 2 是否可以将非零元素保留在原始arr中,并使用掩码仅替换零元素?我希望通过平面索引避免这样做,因为我处理的阵列是大型3D阵列(约1000x1000x1000) 编辑:一些附加信息: 我希望避免更改掩码,这包括在数组非零的情况下将其设置为Fa

考虑二维阵列:

arr = np.zeros((10,10))
arr[3:7,3:7] = 1
现在,我想使用掩码将其中的一部分替换为其他值:

mask = np.ones((5,5)).astype(bool)
arr[5:,5:][mask] = 2
是否可以将非零元素保留在原始
arr
中,并使用掩码仅替换零元素?我希望通过平面索引避免这样做,因为我处理的阵列是大型3D阵列(约1000x1000x1000)

编辑:一些附加信息:


我希望避免更改掩码,这包括在数组非零的情况下将其设置为False以及调整其大小。原因是,将掩模放置在阵列的不同区域时,此操作需要重复多次。由于阵列非常大,因此避免复制数据也很好。

您可以使用pandas轻松做到这一点。要转换为3d阵列,您需要在pandas中使用多索引

import pandas as pd
import numpy as np

arr = np.zeros((10,10))
arr[3:7,3:7] = 1    

df = pd.DataFrame(arr)
df.loc[5:,5:] = df.loc[5:,5:].replace(0,2)

使用
np.logical\u和

arr = np.zeros((10,10))
arr[3:7,3:7] = 1
mask = np.ones((10,10)).astype(bool) #same shape as the array
mask = np.logical_and(mask, arr == 0)
arr[mask] = 2 # replace 0's with whatever value

如果您想应用滑动窗口方法,可以使用extend a bit@Thiru的方法使其工作:

>>> arr = np.zeros((10,10))
>>> arr[3:7,3:7] = 1
>>> mask = np.ones((5,5)).astype(bool)
相应地更新阵列:

>>> CONSTANT = 2
>>> arr[5:,5:] += np.logical_and(mask, arr[5:, 5:] == 0) * CONSTANT
array([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  1.,  1.,  1.,  2.,  2.,  2.],
       [ 0.,  0.,  0.,  1.,  1.,  1.,  1.,  2.,  2.,  2.],
       [ 0.,  0.,  0.,  0.,  0.,  2.,  2.,  2.,  2.,  2.],
       [ 0.,  0.,  0.,  0.,  0.,  2.,  2.,  2.,  2.,  2.],
       [ 0.,  0.,  0.,  0.,  0.,  2.,  2.,  2.,  2.,  2.]])

加法将保持非零元素的原样,
logical_和
将创建一个掩码,该掩码乘以一个常量将在数组为非零和
常量的情况下添加
0
值。

其他人建议
logical_和
,但您反对它涉及太多的复制。但首先,让我们建立一个互动的案例,这样做

In [353]: arr=np.zeros((10,10))
In [354]: arr[3:7,3:7]=1

In [355]: tups=[(slice(5),slice(5)),
                (slice(0,5),slice(3,8)),
                (slice(4,9),slice(1,6))]

In [356]: for i,tup in enumerate(tups):
    mask1=np.logical_and(mask,arr[tup]==0)
    arr[tup][mask1]=i+1
   .....:     

In [357]: arr
Out[357]: 
array([[ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  0.,  0.],
       [ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  0.,  0.],
       [ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  0.,  0.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  2.,  0.,  0.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  2.,  0.,  0.],
       [ 0.,  3.,  3.,  1.,  1.,  1.,  1.,  0.,  0.,  0.],
       [ 0.,  3.,  3.,  1.,  1.,  1.,  1.,  0.,  0.,  0.],
       [ 0.,  3.,  3.,  3.,  3.,  3.,  0.,  0.,  0.,  0.],
       [ 0.,  3.,  3.,  3.,  3.,  3.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])
arr[tup]==0
是另一个掩码。这是唯一一种可以告诉
numpy
您只想更改0的方法。它不会自动将0与1或3区别对待。我看不出有任何方法可以在每一步使用
logical\u和
创建新的掩码


布尔掩码的应用确实涉及平面索引——也就是说,结果是一个1d数组(无论是在右侧还是左侧)

查看应用上一次迭代中的遮罩的结果

In [360]: arr[tup][mask]
Out[360]: 
array([ 1.,  1.,  1.,  1.,  1.,  3.,  3.,  1.,  1.,  1.,  3.,  3.,  1.,
        1.,  1.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.])

In [361]: arr[tup][mask1]
Out[361]: array([ 3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.,  3.])

这里有一个使用
np的替代方法。其中

for i,tup in enumerate(tups):
    arr[tup]=np.where(arr[tup]==0,i+1,arr[tup])
这更简洁,但每次都要编写整个
arr[tup]
切片

In [374]: %%timeit arr=np.zeros((10,10),int);arr[3:7,3:7]=1
   .....: for i,tup in enumerate(tups):
    arr[tup]=np.where(arr[tup]==0,i+1,arr[tup])
   .....: 
1000 loops, best of 3: 134 us per loop

In [375]: %%timeit arr=np.zeros((10,10),int);arr[3:7,3:7]=1
   .....: for i,tup in enumerate(tups):
    mask1=np.logical_and(mask,arr[tup]==0)
    arr[tup][mask1]=i+1p
   .....: 
10000 loops, best of 3: 64.9 us per loop


警告,使用
arr[tup][mask]=…
时,
arr[tup]
必须是视图,例如通过切片生成的视图。其他索引生成一个副本,阻止对原始数组的更改。

这种局部问题使用奇特的索引(真/假掩码),由于在数组上多次传递,通常成本很高

在这种情况下,Numba(或cython)通常是一个很好的改进来源:

def s1(a):
    a[N//2:,N//2:][N//2:, N//2:] == 0] = 30 

from numba import jit
@jit(nopython=True)
def s2(a):
    for i in range(N//2,N):
        for j in range(N//2,N):
            if a[i,j]==0 : a[i,j]=30
100x100阵列的测试:

In [8]: %timeit s1(a)
10000 loops, best of 3: 65.5 µs per loop

In [9]: %timeit s2(a)
100000 loops, best of 3: 10.5 µs per loop

如果数组为非零,可以将掩码设置为零:
mask=np.logical_和(mask,arr==0)
是的,我忘了提到我也会尝试避免,因为将掩码放置在数组的不同区域时,此操作需要重复很多次。所以我需要一直重新生成它..替换零很简单:
arr[arr==0]=value
。我不需要替换所有的零,只需要替换掩码中包含的那些零,好吗?应该只在5:5的方格上替换你的面具。谢谢你的回答。我猜
arr[tup][np.logical_和(mask,arr[tup]==0)]=value
是最好的选择。