当要使用偏移量应用蒙版时,使用蒙版选择多维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
此处发布了类似的问题: Setting values of Numpy array when indexing an indexed array 但我正在使用面具,我不会问为什么它不起作用。
答案 0 :(得分:2)
问题似乎是使用np.ix_
返回的数组作为索引意味着你正在进行高级索引,as the documentation of NumPy states:
高级索引始终返回数据的副本(与返回view的基本切片形成对比)。
但在这种情况下,如果真实的应用程序与您发布的代码类似(也就是说,如果您真的只需要一个偏移量),那么您可以放弃基本的切片:
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
答案 1 :(得分:1)
一种方法是使用线性指数。因此,我们将从np.ix_
获取行索引和列索引,从中获取线性索引等价物。然后,使用mask
选择有效的值,最后使用有效的线性索引为数据数组赋值。
因此,实施将是 -
# 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
答案 2 :(得分:1)
我通常使用辅助函数来创建数组的适当形状的部分(视图):
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
ND实施将如下所示:
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))
答案 3 :(得分:0)
mask=figure>0.5
如果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.]])