在第二维上重叠的块需要使用类似于as_strided
的东西。B.M.先前用as_strided
解决了这个问题,但我发现很难理解。它看起来也很危险,因为显示了越界数据。我正在分步骤接近任务。
对于“cols”的最后一维进行选择[0,1]和[2,3]相对容易。通过变形使其更容易。
In [27]: A=np.arange(36).reshape(3,3,4)
In [28]: A1=A.reshape(3,3,2,2)
In [29]: A2=A1[[0,1,2],:,[0,1,1],:]
In [30]: A2
Out[30]:
array([[[ 0, 1],
[ 4, 5],
[ 8, 9]],
[[14, 15],
[18, 19],
[22, 23]],
[[26, 27],
[30, 31],
[34, 35]]])
针对一个子数组,我发现我可以将其视为2个重叠的数组:
In [59]: as_strided(A2[0],shape=(2,2,2),strides=(8,8,4))
Out[59]:
array([[[0, 1],
[4, 5]],
[[4, 5],
[8, 9]]])
np.lib.stride_tricks.as_strided
是一个难以使用的函数。我看到它主要用于移动窗口的应用程序。
应用于整个数组:
In [65]: A3=as_strided(A2,shape=(3,2,2,2),strides=(24,8,8,4))
In [66]: A3
Out[66]:
array([[[[ 0, 1],
[ 4, 5]],
...
[[30, 31],
[34, 35]]]])
并且目标:
In [71]: A3[[0,1,2],[0,1,0]]
Out[71]:
array([[[ 0, 1],
[ 4, 5]],
[[18, 19],
[22, 23]],
[[26, 27],
[30, 31]]])
这可以通过一种方式组合在一起,允许赋值(形状和步幅从A1
的值适应)。
In [105]: A1 = A.reshape(3,3,2,2)
In [106]: A1s = as_strided(A1, shape=(3,2,2,2,2), strides=(48,16,16,8,4))
In [107]: A1s[[0,1,2],[0,1,0],:,[0,1,1],:]
Out[107]:
array([[[ 0, 1],
[ 4, 5]],
[[18, 19],
[22, 23]],
[[26, 27],
[30, 31]]])
分配测试:
In [108]: A1s[[0,1,2],[0,1,0],:,[0,1,1],:] = 99
In [109]: A
Out[109]:
array([[[99, 99, 2, 3],
[99, 99, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 99, 99],
[20, 21, 99, 99]],
[[24, 25, 99, 99],
[28, 29, 99, 99],
[32, 33, 34, 35]]])
如果您不需要分配任务,那么在没有 striding
的情况下理解逻辑会更容易:
np.array([A2[0,:-1], A2[1,1:], A2[2,:-1]])
slices=(slice(-1),slice(1,None))
np.array([A2[i,slices[j]] for i,j in zip([0,1,2],[0,1,0])])
===========================
之前在寻找答案时遇到的问题:
我认为可以通过高级索引来提取它。
Ind = np.ix_([0,0,1,1,2,2], [0,1,1,2,0,1], [0,1,2,3,2,3])
a[ind]
这些值可能需要微调,因为我无法在这里测试。
思路是枚举每个维度中需要哪些行和列,并使用ix_
(我认为这是正确的函数)添加newaxis
以便它们一起广播。
您对2d情况进行泛化的想法是正确的。诀窍是弄清楚何时需要 np.array([0,1,2])
,以及何时需要使用ix_
或[:,None]
等旋转它。最终我会尝试各种想法。
它可能需要进行调整。
Ind = np.ix_([0,1,2], [0,1,1,2,0,1], [0,1,2,3,2,3])
这不完全正确。它将生成一个3x6x6的数组; 您需要的是3x2x2的数组。
将其重新调整为3x3x2x2可能会更容易地索引最后一维。
另一个答案提到的步幅技巧可能有助于将第二个重叠选择转换为类似的2x2块。 但我需要尝试一下。
我想象中的索引元组形式为([1,2,3],[?,?,?],:,[?,?,?],:)