过滤数组,存储邻接信息

时间:2017-04-07 13:16:35

标签: python arrays algorithm numpy

假设我有(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}}

1 个答案:

答案 0 :(得分:1)

最佳答案可能取决于您想要进行的计算的性质。例如,如果它们可以表示为相邻像素的总和,那么像np.convolvescipy.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