Numpy - 更多基于位置的数组修改
Numpy - even more position-based array modification
我有一个大的二维 numpy 数组,每个值都是 0 或 1。我想创建一个函数,将这个数组作为输入,returns 一个新数组大小相同,其中每个元素都基于上方、下方和任一侧的元素。返回的数组应该有 0 保持 0,如果北边有 1,则每个 1 将获得 +1,右边有 1 则为 +2,下方有 1 则为 +4,左边有 1 则为 +8。这些都堆叠在一起,所以 1 被 1 包围的结果应该是 17。对角线无关紧要。使用显式按位运算(4 位,每个位对应一个方向以及其中是否有 1 或 0),这也可能更快。
我希望尽快完成此操作。我玩过一个 for 循环,但它太慢了,而且我不太了解 numpy 中的屏蔽,无法使用它。
希望对您有所帮助。我开始复制原始矩阵,然后添加每个方向的贡献。例如,如果我必须添加右侧元素的贡献,它们可能会修改除最后一列之外的所有列,因此我可以写 result[:,:-1] += m[:,1:]
。 m
的最后一次乘法确保要修改的每个单元格的起始值为一而不是零,正如您所要求的那样。
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
您描述的操作可以表示为线性卷积,然后将之前为零的点归零:
>>> 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]])
我有一个大的二维 numpy 数组,每个值都是 0 或 1。我想创建一个函数,将这个数组作为输入,returns 一个新数组大小相同,其中每个元素都基于上方、下方和任一侧的元素。返回的数组应该有 0 保持 0,如果北边有 1,则每个 1 将获得 +1,右边有 1 则为 +2,下方有 1 则为 +4,左边有 1 则为 +8。这些都堆叠在一起,所以 1 被 1 包围的结果应该是 17。对角线无关紧要。使用显式按位运算(4 位,每个位对应一个方向以及其中是否有 1 或 0),这也可能更快。
我希望尽快完成此操作。我玩过一个 for 循环,但它太慢了,而且我不太了解 numpy 中的屏蔽,无法使用它。
希望对您有所帮助。我开始复制原始矩阵,然后添加每个方向的贡献。例如,如果我必须添加右侧元素的贡献,它们可能会修改除最后一列之外的所有列,因此我可以写 result[:,:-1] += m[:,1:]
。 m
的最后一次乘法确保要修改的每个单元格的起始值为一而不是零,正如您所要求的那样。
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
您描述的操作可以表示为线性卷积,然后将之前为零的点归零:
>>> 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]])