简体   繁体   English

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

[英]How to loop back to beginning of the array for out of bounds index in numpy?

I have a 2D numpy array that I want to extract a submatrix from.我有一个二维 numpy 数组,我想从中提取一个子矩阵。 I get the submatrix by slicing the array as below.我通过如下切片数组来获得子矩阵。 Here I want a 3*3 submatrix around an item at the index of (2,3).在这里,我想要一个 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]])

But what I want is that for indexes that are out of range, it goes back to the beginning of array and continues from there.但我想要的是对于超出范围的索引,它会回到数组的开头并从那里继续。 This is the result I want:这是我想要的结果:

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

I know that I can do things like getting mod of the index to the width of the array;我知道我可以做一些事情,比如将索引的 mod 获取到数组的宽度; but I'm looking for a numpy function that does that.但我正在寻找可以做到这一点的 numpy function。 And also for an one dimensional array this will cause an index out of range error, which is not really useful...而且对于一维数组,这将导致索引超出范围错误,这并不是很有用......

This is one way using np.pad with wraparound mode.这是使用带有环绕模式的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]])

Depending on the shape of your patch (eg. 5 x 5 instead of 3 x 3) you can increase the pad_width and start and end row and column indices accordingly.根据补丁的形状(例如 5 x 5 而不是 3 x 3),您可以相应地增加pad_width以及开始和结束行和列索引。

np.take does have a mode parameter which can wrap-around out of bound indices. np.take确实有一个mode参数,它可以环绕超出范围的索引。 But it's a bit hacky to use np.take for multidimensional arrays since the axis must be a scalar.但是将np.take用于多维 arrays 有点麻烦,因为axis必须是标量。

However, In your particular case you could do this:但是,在您的特定情况下,您可以这样做:

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]

Output: Output:

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

EDIT编辑

This function might be what you are looking for (?)这 function 可能是您正在寻找的(?)

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')

But in retrospect, i recommend using modulo and fancy indexing for this kind of operation (it's basically what the mode='wrap' is doing internally anyways):但回想起来,我建议对这种操作使用模数和花式索引(这基本上是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]]

The above solution is also generalized for any 2d shape on a .上述解决方案也适用于a上的任何 2d 形状。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM