用于从3-D阵列中选择具有不同起始索引的相同长度子阵列的纯numpy表达式

时间:2016-06-23 06:52:02

标签: python numpy

我有一个形状为numpy的3-D a数组(我们称之为(74, 74, 4563)),我想从中提取长度为n的子数组前两个维度中的每个位置。但是,每个子阵列都在不同的位置开始,具体取决于前两个维度中的索引i& j

例如,如果n=1000,我可能需要a[0, 0, 0:1000],还需要a[0, 1, 2:1002]等...我有一个二维数组(称为ix0)是一个二维数组,告诉我每个子数组在每个i / j位置的起始位置。最后,我保证不会有任何“溢出” - 也就是说,ix0 + n中的所有值都小于a的维度-2长度(因此我们不需要担心要求超出现有范围的指数。

例如......

a = np.arange(74*74*4563).reshape(74, 74, 4563)
ix0 = np.arange(74*74).reshape(74,74)/2 + 50
a[:, :, ix0:ix0+n]

产生

IndexError: failed to coerce slice entry of type numpy.ndarray to integer

有没有办法在不循环遍历所有i / j索引组合或创建大掩码数组的情况下执行此操作?

1 个答案:

答案 0 :(得分:3)

以前曾经问过这条线,但是2d。我可能会试着看一下。

但是这里有一个关于2d案例中发生的事情的简单例子

In [1463]: x=np.arange(12).reshape(3,4)
In [1464]: ix0=np.array([0,2,1])
In [1465]: N=2

我们可以迭代x的每一行,收集所需的N长度切片,然后将它们连接到列表或数组中。更普遍的问题是改变切片的长度,在这种情况下,它们不能重新组装成数组。

In [1466]: [x[i,ix0[i]:ix0[i]+N] for i in range(3)]
Out[1466]: [array([0, 1]), array([6, 7]), array([ 9, 10])]

然后将该列表包装在np.array

另一种方法是首先连接索引:

In [1467]: x[np.arange(3)[:,None], np.array([np.r_[ix0[i]:ix0[i]+N] for i in range(3)])]
Out[1467]: 
array([[ 0,  1],
       [ 6,  7],
       [ 9, 10]])

最后一个索引数组是:

In [1468]: np.array([np.r_[ix0[i]:ix0[i]+N] for i in range(3)])
Out[1468]: 
array([[0, 1],
       [2, 3],
       [1, 2]])

要应用于3d案例,我们有两个选择。一个是重塑为2d,应用其中一个策略,并重新塑造。另一个是概括我为创造这些所采取的行动 - 这不应该太难,但需要进行一些实验。

最后一个数组不应该难以通过广播创建。

In [1469]: ix0[:,None]+np.arange(N)
Out[1469]: 
array([[0, 1],
       [2, 3],
       [1, 2]])

In [1470]: x[np.arange(3)[:,None], ix0[:,None]+np.arange(N)]
Out[1470]: 
array([[ 0,  1],
       [ 6,  7],
       [ 9, 10]])

现在应该更容易概括为3d

In [1487]: X=np.arange(2*3*10).reshape(2,3,10)

In [1488]: ix0=np.arange(2*3).reshape(2,3)

In [1489]: ix0[...,None]+np.arange(N)
Out[1489]: 
array([[[0, 1],
        [1, 2],
        [2, 3]],

       [[3, 4],
        [4, 5],
        [5, 6]]])

In [1490]: I,J,_=np.ix_(range(2),range(3),range(N))

In [1491]: I.shape
Out[1491]: (2, 1, 1)

In [1492]: J.shape
Out[1492]: (1, 3, 1)

In [1493]: X[I, J, ix0[...,None]+np.arange(N)]
Out[1493]: 
array([[[ 0,  1],
        [11, 12],
        [22, 23]],

       [[33, 34],
        [44, 45],
        [55, 56]]])

我应该确保值是正确的,但形状匹配,在这种情况下,这是80%的工作。