索引numpy二维数组以进行环绕。

4
如何索引一个numpy数组,当它越界时会回到边界?
例如,我有一个3x3的数组:
import numpy as np

matrix = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]])

## 
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]
 [11 12 13 14 15]]

假设我想索引值位于(2,4)附近且数值小于15的数据。 我希望获得包含这些值的数组:

[[9,  10, 6]
 [14, 15, 11]
 [4,  5,  1]]

基本上,所有约为15的值都被返回,假设它绕回来了。

看一下 np.take - hpaulj
@hpaulj 像这个一样的东西? - Antony Hatchkins
3个回答

6

numpy 数组中查找相邻元素的一个非常标准的习语是 arr[x-1:x+2, y-1:y+2]。但是,如果您想要环绕,则可以使用包装模式填充数组,并偏移 xy 坐标以解决此填充。

本答案假设您希望查找所需元素的第一个出现的邻居。


首先,找到您的元素的索引,并进行偏移以解决填充问题:

x, y = np.unravel_index((m==15).argmax(), m.shape)
x += 1; y += 1

现在,使用pad函数并索引您的数组以获取邻居:
t = np.pad(m, 1, mode='wrap')    
out = t[x-1:x+2, y-1:y+2]  

array([[ 9, 10,  6],
       [14, 15, 11],
       [ 4,  5,  1]]) 

3

以下是不需要填充的方法。这种方法可以轻松地推广到当您想要多个邻居而无需填充数组时。

def get_wrapped(matrix, i, j):
  m, n = matrix.shape
  rows = [(i-1) % m, i, (i+1) % m]
  cols = [(j-1) % n, j, (j+1) % n]
  return matrix[rows][:, cols]

res = get_wrapped(matrix, 2, 4)

让我解释一下这里发生了什么:return matrix[rows][:, cols]。实际上这是两个操作。

第一个操作是matrix[rows],它是matrix[rows,:]的简写,意思是给我选定的行,并且这些行的所有列。

然后我们进行下一个操作[:,cols],它的意思是给我所有的行和选定的列。


我明白了,这实际上非常灵活,如果我想要两个相邻元素,我只需要在行和列列表中添加2个元素,分别为-2和+2。唯一让我有些困惑的是matrix[rows][:, cols]中的“:”。我认为它只是用于matrix[rows][cols],但显然这不起作用。 - user1179317
1
因此,在numpy中,您可以使用matrix[row, col]来索引矩阵,而不是Python的list[row][col]。所以它实际上是两个单独的索引'a = matrix[rows]'和'b = a[:, cols]'。冒号':'表示所有。 - Silver
1
啊,好的,这很有道理。谢谢你的解释。 - user1179317
1
每个 '[]' 都会被 Python 解释器单独评估。先执行 matrix[rows],然后在结果上执行 [cols]。因此,您必须注意中间结果。在 [rows, cols] 中,numpy 一起处理两个部分。 - hpaulj

0

take 函数是就地操作。

>>> a = np.arange(1, 16).reshape(3,5)
array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10],
       [11, 12, 13, 14, 15]])
>>> b = np.take(a, [3,4,5], axis=1, mode='wrap')
array([[ 4,  5,  1],
       [ 9, 10,  6],
       [14, 15, 11]])
>>> np.take(b, [1,2,3], mode='wrap', axis=0)
array([[ 9, 10,  6],
       [14, 15, 11],
       [ 4,  5,  1]])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接