二维索引和求和的numpy数组

Posted

技术标签:

【中文标题】二维索引和求和的numpy数组【英文标题】:numpy array of 2 dimensions indexing and sum 【发布时间】:2022-01-15 20:12:18 【问题描述】:

我有一个疑问。有没有一种有效的方法可以在不使用多个条件的情况下对 numpy 矩阵的所有邻居求和?

这是一个例子:

array([[5, 4, 8, 3, 1, 4, 3, 2, 2, 3],
       [2, 7, 4, 5, 8, 5, 4, 7, 1, 1],
       [5, 2, 6, 4, 5, 5, 6, 1, 7, 3],
       [6, 1, 4, 1, 3, 3, 6, 1, 4, 6],
       [6, 3, 5, 7, 3, 8, 5, 4, 7, 8],
       [4, 1, 6, 7, 5, 2, 4, 6, 4, 5],
       [2, 1, 7, 6, 8, 4, 1, 7, 2, 1],
       [6, 8, 8, 2, 8, 8, 1, 1, 3, 4],
       [4, 8, 4, 6, 8, 4, 8, 5, 5, 4],
       [5, 2, 8, 3, 7, 5, 1, 5, 2, 6]])

当我运行 m[0][-1] 时,它返回 3 而不是错误,所以如果我想将 1 添加到一个值的所有邻居,我需要使用很多条件,因为我不能只使用 m[0][-1],因为在这种情况下,在角落的其他情况下,它返回给我的只是一个“假邻居”

【问题讨论】:

您的预期输出是什么?你试过什么?你想总结几个邻居? 我认为你只需要添加一个条件,即索引应该是正数。 @UlisesBussi 我想为所有邻居添加 +1 以获得特定值。但是邻居的总数是不同的。例如。对于第一个值 5,邻居是 2;4 和 7。 那么你必须小心限制(当 i=0 或 i=len(m) 和 j=0 或 j=len(m[0]) 时)。这应该是你唯一的条件. 但是您可以调用 make 2 fors 来查找所有邻居或将案例保存为列表 【参考方案1】:

IIUC,您想给具有给定值的单元格的每个邻居加 1。

例如,让我们将 1 添加到 7 附近的每个单元格:

from scipy.signal import convolve2d
v = np.array([[1,1,1],[1,0,1],[1,1,1]])
a + convolve2d(a==7, v, mode='same')

输出:

array([[6, 5, 9, 3, 1, 4, 4, 3, 3, 3],
       [3, 7, 5, 5, 8, 5, 5, 8, 3, 2],
       [6, 3, 7, 4, 5, 5, 7, 3, 8, 4],
       [6, 1, 5, 2, 4, 3, 6, 3, 6, 8],
       [6, 3, 7, 8, 5, 8, 5, 5, 7, 9],
       [4, 2, 9, 9, 7, 2, 5, 8, 6, 6],
       [2, 2, 8, 8, 9, 4, 2, 7, 3, 1],
       [6, 9, 9, 3, 8, 8, 2, 2, 4, 4],
       [4, 8, 4, 7, 9, 5, 8, 5, 5, 4],
       [5, 2, 8, 4, 7, 6, 1, 5, 2, 6]])

【讨论】:

感谢您的回答。如果我想为所有数字/矩阵添加 1 而不是仅靠近单个值? 你能举个例子吗? 抱歉,已解决;)还是谢谢【参考方案2】:

除了良好的@mozway 解决方案之外,一个非常有效的解决方案是使用 Numba 模板装饰器结合并行执行。这是一个例子:

import numba as nb

# parallel=True is only useful for quite-big arrays
@nb.njit(parallel=True)
def kernel(v):
    cond = np.zeros((v.shape[0]+2, v.shape[1]+2), dtype=np.bool_)
    cond[1:-1, 1:-1] = v == 7
    res = nb.stencil(lambda c: c[-1,-1]+c[-1,0]+c[-1,1]+c[0,-1]+c[0,1]+c[1,-1]+c[1,0]+c[1,1])(cond)
    return v + res[1:-1, 1:-1]

kernel(m)

更快的解决方案在于就地工作(使用v += res而不是return v + res)。以下是我的 6 核机器上 2000x2000 整数数组的性能结果:

scipy.signal.convolve2d:  124 ms
Numba out-of-place:        20 ms
Numba in-place:            15 ms

请注意,由于编译时间的原因,第一次调用 kernel 会比较慢。 对于较小的阵列 (200x200),我也获得了类似的加速。

【讨论】:

以上是关于二维索引和求和的numpy数组的主要内容,如果未能解决你的问题,请参考以下文章

按索引对numpy数组的累积求和

numpy数组-二维数组的轴

Numpy:将值分配给具有索引列表的二维数组

Python numpy 保留已排序二维数组的索引列表

numpy 切片和索引

使用 numpy 数组有效地索引 numpy 数组