使用提供的索引对NumPy 2D数组进行索引区域。

huangapple go评论73阅读模式
英文:

indexing area in numpy 2D array, using a 2D array providing the indices

问题

你想要使用另一个提供索引对的2D数组来索引或提取numpy 2D数组的区域,类似于 https://stackoverflow.com/a/14999290/17173241 中的示例。

a = np.arange(36).reshape(6,6) 
b = np.array([[0,1],[1,2],[2,1],[3,3],[4,4],[5,3]])
result = a[b[:,0],b[:,1]]

这个例子中的代码会按预期工作。

现在,你想使用b的第二个索引作为范围的中间点,以每行不仅提取单个点,而是提取每行的3个点。你可以尝试以下方法:

result = a[b[:,0], b[:,1]-1:b[:,1]+2]

这将给你每行的3个点。

如果你要处理索引超出边界的情况,你可以使用np.clip来确保索引不会超出边界:

result = a[b[:,0], np.clip(b[:,1]-1, 0, a.shape[1]-1):np.clip(b[:,1]+2, 0, a.shape[1])]

这将避免获取每行的末尾值,而是获取零值,如果索引变得负数。

希望这有助于你完成你的任务!

英文:

Suppose I have a numpy 2D array and I want to index or extract a region of it using another 2D array which provides the index pairs, similar as in 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])

this works as intended.
Now I want to use the second index of b as e.g. the mid point of a range, to extract not only single points in a for each row, but lets say 3 points together per row. How do I do it?

I tried

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

but this gives a TypeError, which I cannot think through..

I came up with this attempt, because I thought it is similar to

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

although of course the last example uses always the same indices as the second index.

I also tried this:

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

yields the lower and upper bound of my range as it is read as a tuple, I guess.
I want to achieve something like

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

or even better

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

BONUS: for a range that wide, that indices become negative i.e., b[:,1]-2:b[:,1]+1],
how would I avoid getting values from the end of each row, but instead getting zeros.

答案1

得分: 1

I'll provide the translated code parts for you:

# 原始数组
x = np.arange(9).reshape(3,3) * 10.0
x

# 行索引 (3,1) 的形状
b1 = np.arange(3)[:, None]
b1

# 列索引 (3,2),注意 (3,1) 会与 (3,2) 广播:
b2 = np.array([[0, 1], [1, 2], [0, 2]])
b2

# 通过 linspace 生成 `b2` 数组
b2 = np.linspace([0, 1, 1], [1, 2, 2], 2).astype(int)
b2

# 使用广播索引
x[b1, b2.T]

# 关键是 `b1` 和 `b2` 需要广播。
# `np.take_along_axis` 是一个新函数,可以处理创建 `b1` 数组的工作,其余部分相同。

This provides the translated code segments without additional content.

英文:

I'll show how to index 2 items from each row of a (3,3) array. Hopefully it gives an idea that can be generalized. I need to clean up the copy-n-paste from the ipython qtconsole session, but here's a start

The wource array

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

row index (3,1) shape

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

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

column index (3,2). Note that (3,1) broadcasts with (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.]])

Using linspace to generate b2 from ranges

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.]])

The key is that b1 and b2 need to broadcast.

np.take_along_axis is a new function that can take care of creating the b1 array. Otherwise it functions the same way.

答案2

得分: 0

你的初始问题可以通过内联for循环解决:

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

但是,你不能使用c[a, b]方法来访问这个列表的元素,你必须使用c[a][b]

英文:

Your initial question can be solved with an inline for loop:

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

However, you can't access elements of this list using the c[a, b] method, you have to use c[a][b]

huangapple
  • 本文由 发表于 2023年5月13日 23:13:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76243452.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定