numpy 2D数组中的索引区域,使用提供索引的2D数组

qco9c6ql  于 2023-05-22  发布在  其他
关注(0)|答案(2)|浏览(146)

假设我有一个numpy 2D数组,我想使用另一个提供索引对的2D数组索引或提取它的一个区域,类似于https://stackoverflow.com/a/14999290/17173241:

a = np.arange(36).reshape(6,6) 
>>> a
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35]])

b = np.array([[0,1],[1,2],[2,1],[3,3],[4,4],[5,3]]) 
>>> b
array([[0, 1],
       [1, 2],
       [2, 1],
       [3, 3],
       [4, 4],
       [5, 3]])

>>> a[b[:,0],b[:,1]]
array([ 1,  8, 13, 21, 28, 33])

这如预期的那样工作。现在我想使用B的第二个索引作为例如。范围的中点,以不仅为每行提取A中的单个点,而且假设每行一起提取3个点。我该怎么做?
我尽力了

>>> a[b[:,0],b[:,1]-1:b[:,1]+1] 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: only integer scalar arrays can be converted to a scalar index

但是这给出了一个TypeError,我无法理解。
我想出了这个尝试,因为我认为它类似于

>>> a[b[:,0],1:3] 
array([[ 1,  2],
       [ 7,  8],
       [13, 14],
       [19, 20],
       [25, 26],
       [31, 32]])

尽管当然最后一个例子总是使用与第二索引相同的索引。
我也试过这个:

>>> a[b[:,0],(b[:,1]-1,b[:,1]+1)]
array([[ 0,  7, 12, 20, 27, 32],        
       [ 2,  9, 14, 22, 29, 34]])

我猜,当它被读取为元组时,会产生我的范围的上下界。我想达到这样的目标

array([[ 0,  7, 12, 20, 27, 32],
       [ 1,  8, 13, 21, 28, 33]
       [ 2,  9, 14, 22, 29, 34]])

甚至更好

array([[ 0, 1, 2],
       [ 7, 8, 9],
       [12, 13, 14],
       [20, 21, 22],
       [27, 28, 29],
       [32, 33, 34]])

额外的好处:对于一个如此宽的范围,索引变为负值,即b[:,1]-2:b[:,1]+1],我如何避免从每行的末尾获得值,而是获得零。

vlju58qv

vlju58qv1#

我将展示如何从(3,3)数组的每一行索引2项。希望它能给出一个可以推广的想法。我需要清理IPythonQtConsole会话中的copy-n-paste,但这里是一个开始
源数组

x=np.arange(9).reshape(3,3)*10.0    
x
Out[3]: 
array([[ 0., 10., 20.],
       [30., 40., 50.],
       [60., 70., 80.]])

行索引(3,1)形状

b1=np.arange(3)[:,None]

b1
Out[6]: 
array([[0],
       [1],
       [2]])

列索引(3,2)。请注意,(3,1)与(3,2)广播:

b2=np.array([[0,1],[1,2],[0,2]])

b2
Out[9]: 
array([[0, 1],
       [1, 2],
       [0, 2]])

In [10]: x[b1,b2]
Out[10]: 
array([[ 0., 10.],
       [40., 50.],
       [60., 80.]])

使用linspace从范围生成b2

In [14]: b2=np.linspace([0,1,1],[1,2,2],2).astype(int)

In [15]: b2
Out[15]: 
array([[0, 1, 1],
       [1, 2, 2]])

In [16]: x[b1,b2.T]
Out[16]: 
array([[ 0., 10.],
       [40., 50.],
       [70., 80.]])

关键是b1b2需要广播。
np.take_along_axis是一个新函数,它可以创建b1数组。否则,它以相同的方式运行。

k4ymrczo

k4ymrczo2#

你最初的问题可以通过一个内联for循环来解决:

c = [a[i[0], (i[1]-1):(i[1]+2)] for i in b]

但是,您不能使用c[a, b]方法访问此列表中的元素,必须使用c[a][b]

相关问题