Python NumPy复杂切片

Python NumPy复杂切片,python,numpy,slice,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]]) 是否有方法获取包含第

我有一个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]])
显然,我想要一种通用的方法,它可以有效地处理多维大阵列(不仅仅是上面的玩具示例)。

试试:

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

只要行之间的偏移一致,就可以使用:

# 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_brand
功能强大得不可思议,所以在使用时要非常小心。例如,绝对确保视图在最后几行中没有超出边界

如果可以避免,请尽量不要将任何内容分配到
所返回的视图中。如果您不确切知道自己在做什么,则赋值只会增加不可预知行为和崩溃的危险数千倍。

只要行之间的偏移量一致,您就可以使用:

# 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_brand
功能强大得不可思议,所以在使用时要非常小心。例如,绝对确保视图在最后几行中没有超出边界


如果可以避免,请尽量不要将任何内容分配到
所返回的视图中。如果你不确切知道自己在做什么,任务只会增加不可预知的行为和崩溃的危险一千倍

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]

所以你可以根据你的需要修改它。祝你好运

我猜是这样的: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]

所以你可以根据你的需要修改它。祝你好运

我将提取对角线向量并将它们堆叠在一起,如下所示:

def diag_slice(x, start, end):
    n_rows = min(*x.shape)-end+1
    columns = [x.diagonal(i)[:n_rows, None] for i in range(start, end)]
    return np.hstack(columns)

In [37]: diag_slice(x, 1, 3)
Out[37]: 
array([[7, 3],
       [5, 7],
       [3, 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])

我将提取对角线向量并将它们堆叠在一起,如下所示:

def diag_slice(x, start, end):
    n_rows = min(*x.shape)-end+1
    columns = [x.diagonal(i)[:n_rows, None] for i in range(start, end)]
    return np.hstack(columns)

In [37]: diag_slice(x, 1, 3)
Out[37]: 
array([[7, 3],
       [5, 7],
       [3, 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])

在一般情况下,很难击败逐行列表理解:

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])]
如果生成的阵列大小相同,则可以将它们组合成一个二维阵列:

In [30]: np.array(_)
Out[30]: 
array([[7, 8],
       [2, 0],
       [9, 2]])
另一种方法是连接之前的索引。我将不深入讨论细节,但创建如下内容:

def diag_slice(x, start, end):
    n_rows = min(*x.shape)-end+1
    columns = [x.diagonal(i)[:n_rows, None] for i in range(start, end)]
    return np.hstack(columns)

In [37]: diag_slice(x, 1, 3)
Out[37]: 
array([[7, 3],
       [5, 7],
       [3, 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_跨步的技巧可能更快,但需要更多的理解


还提出了一些基于掩蔽的方法。但是细节更复杂,所以我将把这些留给像@Divakar这样专门研究它们的人。

对于一般情况,很难击败逐行列表理解:

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])]
如果生成的阵列大小相同,则可以将它们组合成一个二维阵列:

In [30]: np.array(_)
Out[30]: 
array([[7, 8],
       [2, 0],
       [9, 2]])
另一种方法是连接之前的索引。我将不深入讨论细节,但创建如下内容:

def diag_slice(x, start, end):
    n_rows = min(*x.shape)-end+1
    columns = [x.diagonal(i)[:n_rows, None] for i in range(start, end)]
    return np.hstack(columns)

In [37]: diag_slice(x, 1, 3)
Out[37]: 
array([[7, 3],
       [5, 7],
       [3, 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_跨步的技巧可能更快,但需要更多的理解


还提出了一些基于掩蔽的方法。但是细节更复杂,所以我将把这些留给像@Divakar这样专门研究它们的人。

有人已经指出了
的技巧,是的,你真的应该谨慎使用

这是一种广播/花式索引方法,它的效率不如_大步前进时的
,但在我看来仍然非常有效

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]

有人已经指出了
的技巧,是的,你应该谨慎使用

这是一种广播/花式索引方法,它的效率不如_大步前进时的
,但在我看来仍然非常有效

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]

第三排和第五排呢?还有,所有窗户的长度都一样吗?第三排和第五排呢?另外,所有窗口的长度是否相同?请注意,这会通过包装在np.array中生成一个副本;我相信这(可能)是一个没有that@en_Knight这将是一个视图列表。请注意,这将通过包装在np.array中生成一个副本;我相信这(可能)是一个没有that@en_Knight这将是一个视图列表。