如何在numpy中循环回数组的开头以获取越界索引?

yv5phkfx  于 2021-07-13  发布在  Java
关注(0)|答案(2)|浏览(301)

我有一个2d numpy数组,我想从中提取一个子矩阵。我得到子矩阵切片数组如下。这里我想要一个3*3的子矩阵,围绕着索引为(2,3)的项。

>>> import numpy as np
>>> a = np.array([[0, 1, 2, 3],
...        [4, 5, 6, 7],
...        [8, 9, 0, 1],
...        [2, 3, 4, 5]])
>>> a[1:4, 2:5]
array([[6, 7],
   [0, 1],
   [4, 5]])

但我想要的是,对于超出范围的索引,它返回到数组的开头,并从那里继续。这就是我想要的结果:

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

我知道我可以做一些事情,比如将索引的mod设置为数组的宽度;但我正在寻找一个numpy函数来实现这个功能。而且对于一维数组,这也会导致索引超出范围的错误,这不是真正有用的。。。

ie3xauqp

ie3xauqp1#

这是使用 np.pad 带环绕模式。

>>> a = np.array([[0, 1, 2, 3],
                  [4, 5, 6, 7],
                  [8, 9, 0, 1],
                  [2, 3, 4, 5]])

>>> pad_width = 1
>>> i, j = 2, 3

>>> startrow, endrow = i-1+pad_width, i+2+pad_width # for 3 x 3 submatrix
>>> startcol, endcol = j-1+pad_width, j+2+pad_width

>>> np.pad(a, (pad_width, pad_width), 'wrap')[startrow:endrow, startcol:endcol]
array([[6, 7, 4],
       [0, 1, 8],
       [4, 5, 2]])

根据贴片的形状(例如5 x 5而不是3 x 3),可以增加 pad_width 并相应地开始和结束行和列索引。

xt0899hw

xt0899hw2#

np.take 有一个 mode 参数,该参数可以环绕越界索引。但使用起来有点麻烦 np.take 对于多维数组 axis 必须是标量。
但是,在您的特定情况下,您可以这样做:

a = np.array([[0, 1, 2, 3],
              [4, 5, 6, 7],
              [8, 9, 0, 1],
              [2, 3, 4, 5]])

np.take(a, np.r_[2:5], axis=1, mode='wrap')[1:4]

输出:

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

编辑
此函数可能就是您要查找的(?)

def select3x3(a, idx):
    x,y = idx
    return np.take(np.take(a, np.r_[x-1:x+2], axis=0, mode='wrap'), np.r_[y-1:y+2], axis=1, mode='wrap')

但回顾过去,我建议对这种操作使用模和花哨的索引(基本上是 mode='wrap' 不管怎么说,都是在内部进行的):

def select3x3(a, idx):
    x,y = idx
    return a[np.r_[x-1:x+2][:,None] % a.shape[0], np.r_[y-1:y+2][None,:] % a.shape[1]]

上述解也可推广到平面上的任意二维形状 a .

相关问题