NumPy复杂切片

时间:2018-08-21 14:57:09

标签: python numpy slice

我有一个NumPy数组,例如:

>>> import numpy as np
>>> x = np.random.randint(0, 10, size=(5, 5))
>>> x
array([[4, 7, 3, 7, 6],
       [7, 9, 5, 7, 8],
       [3, 1, 6, 3, 2],
       [9, 2, 3, 8, 4],
       [0, 9, 9, 0, 4]])

是否有一种方法来获取包含第一行的索引1:3,第二行的索引2:4和第四行的索引3:5的视图(或副本)? 因此,在上面的示例中,我希望获得:

>>> # What to write here?
array([[7, 3],
      [5, 7],
      [8, 4]])

很显然,我希望有一种通用方法也可以对多维大数组有效(并且不仅适用于上面的玩具示例)。

6 个答案:

答案 0 :(得分:2)

尝试:

>>> np.array([x[0, 1:3], x[1, 2:4], x[3, 3:5]])
array([[7, 3],
       [5, 7],
       [8, 4]])

答案 1 :(得分:2)

只要行之间的偏移量是均匀的,就可以使用numpy.lib.stride_tricks.as_strided

# How far to step along the rows
offset = 1
# How wide the chunk of each row is
width = 2
view = np.lib.stride_tricks.as_strided(x, shape=(x.shape[0], width), strides=(x.strides[0] + offset * x.strides[1],) + x.strides[1:])

保证结果是原始数据的视图,而不是副本。

由于as_strided功能强大,因此请务必谨慎使用。例如,绝对确保视图在最后几行中不会超出范围。

如果可以避免,请尽量不要在as_strided返回的视图中分配任何内容。如果您不确切地知道自己在做什么,那么分配只会增加行为无法预测的危险,并且崩溃的危险会翻倍。

答案 2 :(得分:0)

我猜是这样的:D

In:

import numpy as np
x = np.random.randint(0, 10, size=(5, 5))
Out:

array([[7, 3, 3, 1, 9],
       [6, 1, 3, 8, 7],
       [0, 2, 2, 8, 4],
       [8, 8, 1, 8, 8],
       [1, 2, 4, 3, 4]])
In:

list_of_indicies = [[0,1,3], [1,2,4], [3,3,5]] #[row, start, stop]

def func(array, row, start, stop):
    return array[row, start:stop]

for i in range(len(list_of_indicies)):
    print(func(x,list_of_indicies[i][0],list_of_indicies[i][1], list_of_indicies[i][2]))

Out:

[3 3]
[3 8]
[3 4]

因此您可以根据需要进行修改。祝你好运!

答案 3 :(得分:0)

我将提取对角矢量并将它们堆叠在一起,就像这样:

''

答案 4 :(得分:0)

在一般情况下,很难逐行理解:

In [28]: idx = np.array([[0,1,3],[1,2,4],[4,3,5]])
In [29]: [x[i,j:k] for i,j,k in idx]
Out[29]: [array([7, 8]), array([2, 0]), array([9, 2])]

如果结果数组的大小都相同,则可以将它们合并为一个2d数组:

In [30]: np.array(_)
Out[30]: 
array([[7, 8],
       [2, 0],
       [9, 2]])

另一种方法是在之前连接索引。我不会详细介绍,但创建类似这样的内容:

In [27]: x[[0,0,1,1,3,3],[1,2,2,3,3,4]]
Out[27]: array([7, 8, 2, 0, 3, 8])

从不同的行中选择会使第二种方法复杂化。从概念上讲,第一个更简单。过去的经验表明,速度大致相同。

对于均匀长度的切片,诸如as_strided技巧之类的方法可能更快,但是需要更多的了解。

还提出了一些基于掩蔽的方法。但是细节更加复杂,因此我将把那些留给像@Divakar这样专门从事这些工作的人处理。

答案 5 :(得分:0)

有人已经指出了as_strided的窍门,是的,您应该谨慎使用它。

这是一种广播/花式索引方法,效率不如as_strided,但在IMO上仍然运行良好

window_size, step_size = 2, 1

# index within window
index = np.arange(2)

# offset
offset = np.arange(1, 4, step_size)

# for your case it's [0, 1, 3], I'm not sure how to generalize it without further information
fancy_row = np.array([0, 1, 3]).reshape(-1, 1)

# array([[1, 2],
#        [2, 3],
#        [3, 4]])
fancy_col = offset.reshape(-1, 1) + index

x[fancy_row, fancy_col]