Numpy - 更多基于位置的阵列修改

时间:2018-01-26 00:56:07

标签: python arrays numpy masked-array

我有一个大的2维numpy数组,每个值都是0或1.我想创建一个以此数组作为输入的函数,并返回一个相同大小的新数组其中每个元素都基于上面,下面和任何一边的元素。返回的数组应该有0保持为0,如果北方有1,则每个1将获得+1,右边为1,+ 1为1,+ 4为1,+ 8为1向左转。这些都是叠加的,因此被1包围的1应该最终为17.对角线无关紧要。使用显式按位运算(使用4位,每个位对应一个方向以及其中是否存在1或0)时,这也可能更快。

我希望尽快完成此操作。我玩了一个for循环,但它太慢了,而且我不太了解在numpy中掩盖,以便使用它。

2 个答案:

答案 0 :(得分:1)

您描述的操作可以表示为线性卷积,然后将之前为零的点清零:

>>> import numpy as np
>>> from scipy import signal
>>> 
>>> kernel = np.array([[0,1,0], [8,1,2], [0,4,0]])[::-1, ::-1]
>>> 
>>> pattern = np.random.randint(0, 2, (10, 10))
>>> 
>>> pattern
array([[0, 1, 1, 1, 1, 1, 1, 0, 1, 1],
       [1, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 1, 0, 1, 1, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 0, 1, 1, 0, 0, 0],
       [0, 1, 0, 1, 1, 1, 1, 1, 1, 1],
       [0, 1, 0, 0, 0, 1, 0, 1, 1, 0],
       [0, 0, 0, 1, 1, 0, 1, 0, 1, 0],
       [0, 1, 0, 0, 0, 0, 1, 0, 1, 0],
       [0, 1, 1, 1, 0, 1, 0, 1, 1, 0],
       [0, 1, 0, 1, 1, 1, 0, 1, 0, 0]])
>>> 
>>> pattern * signal.convolve(pattern, kernel, 'same')
array([[ 0,  3, 15, 11, 15, 11,  9,  0,  3,  9],
       [ 1,  0,  2,  0,  6,  0,  0,  0,  0,  0],
       [ 0,  1,  0,  3, 12, 13,  0,  1,  0,  1],
       [ 1,  0,  1,  0,  0,  8, 13,  0,  0,  0],
       [ 0,  5,  0,  3, 11, 16, 12, 15, 15,  9],
       [ 0,  2,  0,  0,  0,  2,  0,  4, 14,  0],
       [ 0,  0,  0,  3,  9,  0,  5,  0,  6,  0],
       [ 0,  5,  0,  0,  0,  0,  2,  0,  6,  0],
       [ 0,  8, 11, 13,  0,  5,  0,  7, 10,  0],
       [ 0,  2,  0,  4, 11, 10,  0,  2,  0,  0]])

答案 1 :(得分:0)

我希望这可以提供帮助。我开始复制原始矩阵,然后从每个方向添加贡献。例如,如果我必须在右边添加元素的贡献,它们可以修改所有列但是最后一列,因此我可以编写result[:,:-1] += m[:,1:]m的最后一个乘法确保要修改的每个单元格的起始值为1而不是零,如您所需。

import numpy as np

def f(m):
    result = np.copy(m)
    # propagation from the four directions
    result[1:,:] += m[:-1,:]  # north
    result[:,:-1] += 2 * m[:,1:]  # est
    result[:-1,:] += 4 * m[1:,:]  # sud
    result[:,1:] += 8 * m[:,:-1]  # west
    return result * m