假设我有(N, N)
import numpy as np
my_array = np.random.random((N, N))
形状的二维my_mask = np.zeros_like(my_array, bool)
my_mask[40:61,40:61] = True
my_array[my_mask] = some_twisted_computations(my_array[my_mask])
:
some_twisted_computations()
现在我想只对这个数组的某些“单元”进行一些计算,例如数组中心部分的单元。为了避免对我不感兴趣的单元格进行计算,我通常在这里做的是创建一个布尔掩码,本着这种精神:
mask
但是,如果(len(my_mask), 4)
涉及my_array[mask]
内的相邻单元格的值,那该怎么办?在性能方面,创建一个some_twisted_computations()
形状的“邻接数组”是一个好主意,将我将在(1000,1000,1000)
数组中使用的4个连接的相邻单元的索引存储在wall = mask
i = 0
top_neighbors = []
down_neighbors = []
left_neighbors = []
right_neighbors = []
indices = []
for index, val in np.ndenumerate(wall):
if not val:
continue
indices += [index]
if wall[index[0] + 1, index[1]]:
down_neighbors += [(index[0] + 1, index[1])]
else:
down_neighbors += [i]
if wall[index[0] - 1, index[1]]:
top_neighbors += [(index[0] - 1, index[1])]
else:
top_neighbors += [i]
if wall[index[0], index[1] - 1]:
left_neighbors += [(index[0], index[1] - 1)]
else:
left_neighbors += [i]
if wall[index[0], index[1] + 1]:
right_neighbors += [(index[0], index[1] + 1)]
else:
right_neighbors += [i]
i += 1
top_neighbors = [i if type(i) is int else indices.index(i) for i in top_neighbors]
down_neighbors = [i if type(i) is int else indices.index(i) for i in down_neighbors]
left_neighbors = [i if type(i) is int else indices.index(i) for i in left_neighbors]
right_neighbors = [i if type(i) is int else indices.index(i) for i in right_neighbors]
数组中{1}}?如果是,那么计算这种邻接数组的有效选择是什么?我应该切换到较低级别的语言/其他数据结构吗?
我的真实世界数组形状在{{1}}左右,掩模仅涉及这些值的一小部分(~100000),并且具有相当复杂的几何形状。我希望我的问题有意义......
编辑:我已经解决的非常肮脏和缓慢的解决方案:{{1}}
答案 0 :(得分:1)
最佳答案可能取决于您想要进行的计算的性质。例如,如果它们可以表示为相邻像素的总和,那么像np.convolve
或scipy.signal.fftconvolve
这样的东西可能是一个非常好的解决方案。
对于有效生成邻居索引数组的具体问题,您可以尝试这样的事情:
x = np.random.rand(100, 100)
mask = x > 0.9
i, j = np.where(mask)
i_neighbors = i[:, np.newaxis] + [0, 0, -1, 1]
j_neighbors = j[:, np.newaxis] + [-1, 1, 0, 0]
# need to do something with the edge cases
# the best choice will depend on your application
# here we'll change out-of-bounds neighbors to the
# central point itself.
i_neighbors = np.clip(i_neighbors, 0, 99)
j_neighbors = np.clip(j_neighbors, 0, 99)
# compute some vectorized result over the neighbors
# as a concrete example, here we'll do a standard deviation
result = x[i_neighbors, j_neighbors].std(axis=1)
结果是与屏蔽区域对应的值数组,包含相邻值的标准偏差。 希望这种方法适用于您想到的任何具体问题!
编辑:鉴于上面编辑的问题,这里是我的响应如何适应以矢量化方式生成索引数组:
x = np.random.rand(100, 100)
mask = x > -0.9
i, j = np.where(mask)
i_neighbors = i[:, np.newaxis] + [0, 0, -1, 1]
j_neighbors = j[:, np.newaxis] + [-1, 1, 0, 0]
i_neighbors = np.clip(i_neighbors, 0, 99)
j_neighbors = np.clip(j_neighbors, 0, 99)
indices = np.zeros(x.shape, dtype=int)
indices[mask] = np.arange(len(i))
neighbor_in_mask = mask[i_neighbors, j_neighbors]
neighbors = np.where(neighbor_in_mask,
indices[i_neighbors, j_neighbors],
np.arange(len(i))[:, None])
left_indices, right_indices, top_indices, bottom_indices = neighbors.T