Python 如何使用索引和布尔索引有效地设置numpy数组的值?

Python 如何使用索引和布尔索引有效地设置numpy数组的值?,python,numpy,multidimensional-array,Python,Numpy,Multidimensional Array,当使用偏移量应用遮罩时,使用遮罩选择多维numpy数组的元素最有效的方法是什么?例如: import numpy as np # in real application, following line would read an image figure = np.random.uniform(size=(4, 4)) # used as a mask canvas = np.zeros((10, 10)) # The following doesn't do anything, beca

当使用偏移量应用遮罩时,使用遮罩选择多维numpy数组的元素最有效的方法是什么?例如:

import numpy as np

# in real application, following line would read an image
figure = np.random.uniform(size=(4, 4))  # used as a mask
canvas = np.zeros((10, 10))

# The following doesn't do anything, because a copy is modified
canvas[np.ix_(np.arange(4) + 3, range(4))][figure > 0.5] = 1.0

print np.mean(figure > 0.5)  # should be ~ 0.5
print canvas.max()  # prints 0.0
类似的问题发布在这里:
但我使用的是一个掩码,我并不是在问它为什么不起作用。

问题似乎是,使用np.ix返回的数组作为索引意味着您正在进行高级索引,并且:

高级索引始终返回数据的副本(与返回数据的基本切片相反)

但在这种情况下,如果实际应用程序与您发布的代码相似(即,如果您真的只需要偏移量),则可以使用基本切片:

import numpy as np

figure = np.random.uniform(size=(4, 4))
canvas = np.zeros((10, 10))

# Either of the following works fine
canvas[3:(3 + 4), :4][figure > 0.5] = 1.0
canvas[slice(3, 3 + 4), slice(4)][figure > 0.5] = 1.0

print np.mean(figure > 0.5)  # ~ 0.5
print canvas.max()  # Prints 1.0 now

一种方法是使用线性指数。因此,我们将从
np.ix_uu
中获得行和列索引,并从这些索引中获得线性索引等价物。然后,使用
掩码
选择有效的值,最后使用有效的线性索引将新值分配给数据数组

因此,执行工作将是非常重要的-

# Get the open mesh arrays from np.ix_ corresponding to row, col indices
row, col = np.ix_(np.arange(4) + 3, range(4))

# Get the linear indices from those row and column index arrays 
linear_index = (row*canvas.shape[1] + col)[figure>0.5]

# Finally, assign values
np.put(canvas, linear_index, 1.0) # Or canvas.ravel()[linear_index] = 1.0

我通常使用辅助函数来创建阵列的适当形状部分(视图):

arr = np.ones((10, 10)) * 10
mask = np.random.uniform(size=(4, 4))

def get_part(arr, shape, offs_x, offs_y):
    # This example just does 2D but can easily be expanded for ND-arrays
    return arr[offs_x : (offs_x + shape[0]), 
               offs_y : (offs_y + shape[1])]

get_part(arr, mask.shape, offs_x=3, offs_y=4)[mask > 0.5] = 1.0
AND实现如下所示:

def get_part(arr, shape, offsets):
    slices = tuple(slice(offs, offs+length) for offs, length in zip(offsets, shape))
    return arr[slices]

get_part(arr, mask.shape, (3, 4))
如果
ix
索引确实是范围,则可以用切片替换,如
@jdehesa
所示:

canvas[3:3+4,:4][mask]=1
如果使用
arange
只是一个方便的例子,我们可以使用两阶段分配

In [277]: idx=np.ix_(np.arange(4) + 3, range(4))
In [278]: canvas = np.zeros((10, 10))
In [279]: subcanvas=np.zeros_like(figure)
In [280]: subcanvas[mask] = 1
In [281]: subcanvas
Out[281]: 
array([[ 0.,  1.,  1.,  1.],
       [ 0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  1.]])
In [282]: canvas[idx]=subcanvas
In [283]: canvas
Out[283]: 
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.,  1.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  1.,  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.,  0.,  0.,  0.]])

您是否总是将开放网格数组作为具有序列号的数组?
In [277]: idx=np.ix_(np.arange(4) + 3, range(4))
In [278]: canvas = np.zeros((10, 10))
In [279]: subcanvas=np.zeros_like(figure)
In [280]: subcanvas[mask] = 1
In [281]: subcanvas
Out[281]: 
array([[ 0.,  1.,  1.,  1.],
       [ 0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  1.]])
In [282]: canvas[idx]=subcanvas
In [283]: canvas
Out[283]: 
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.,  1.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  1.,  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.,  0.,  0.,  0.]])