将ndarray分成大块 - 同时保持秩序

时间:2016-05-01 11:00:30

标签: python numpy

我正在尝试实现一个函数,它可以将3维numpy数组拆分为8个,同时保持订单完好无损。基本上我需要分裂:

G[:21, :18,:25]
G[21:, :18,:25]
G[21:, 18:,:25]
G[:21, 18:,:25]
G[:21, :18,25:]
G[21:, :18,25:]
G[21:, 18:,25:]
G[:21, 18:,25:]

此特定矩阵的原始大小为42,36,50。如何概括这些8"切片"所以我不必硬编码所有这些?基本上将:移到每个可能的位置。

谢谢!

1 个答案:

答案 0 :(得分:1)

您可以将1d切片应用于连续(维度列表)。

使用较小的3d数组

In [147]: X=np.arange(4**3).reshape(4,4,4)

复合列表推导产生嵌套列表。在这里,我使用最简单的双拆分

In [148]: S=[np.split(z,2,0) for y in np.split(X,2,2) for z in np.split(y,2,1)]

在这种情况下,所有子列表都具有相同的大小,因此我可以将其转换为数组以方便查看:

In [149]: SA=np.array(S)

In [150]: SA.shape
Out[150]: (4, 2, 2, 2, 2)

有8个子阵列,但分组(4,2)。

In [153]: SAA = SA.reshape(8,2,2,2)

In [154]: SAA[0]
Out[154]: 
array([[[ 0,  1],
        [ 4,  5]],

       [[16, 17],
        [20, 21]]])

In [155]: SAA[1]
Out[155]: 
array([[[32, 33],
        [36, 37]],

       [[48, 49],
        [52, 53]]])

订单是对的吗?我可以通过在3次拆分操作中更改轴来更改它。

另一种方法是将索引表达式编写为元组

In [156]: x,y,z = 2,2,2   # define the split points

In [157]: ind = [(slice(None,x), slice(None,y), slice(None,z)),     
                 (slice(x,None), slice(None,y), slice(None,z)),]  
                 # and so on

In [158]: S1=[X[i] for i in ind]

In [159]: S1[0]
Out[159]: 
array([[[ 0,  1],
        [ 4,  5]],

       [[16, 17],
        [20, 21]]])

In [160]: S1[1]
Out[160]: 
array([[[32, 33],
        [36, 37]],

       [[48, 49],
        [52, 53]]])

看起来和我之前的订单相同。

可以使用某种迭代和/或列表推导来生成ind元组列表。甚至可能使用itertools.productnp.mgrid来生成排列。

itertools.product版本看起来像

In [220]: def foo(i):
    return [(slice(None,x) if j else slice(x,None)) 
            for j,x in zip(i,[2,2,2])]

In [221]: SAA = np.array([X[foo(i)] for i in 
    itertools.product(range(2),range(2),range(2))])

In [222]: SAA[-1]
Out[222]: 
array([[[ 0,  1],
        [ 4,  5]],

       [[16, 17],
        [20, 21]]])

product最快迭代最后一个值,因此列表相反(与目标相比)。

要生成特定的顺序,可能更容易明确地列出元组,例如:

In [227]: [X[foo(i)] for i in [(1,1,1),(0,1,1),(0,0,1)]]
Out[227]: 
[array([[[ 0,  1],
         [ 4,  5]],

        [[16, 17],
         [20, 21]]]), array([[[32, 33],
         [36, 37]],

        [[48, 49],
         [52, 53]]]), array([[[40, 41],
         [44, 45]],

        [[56, 57],
         [60, 61]]])]

这突出了这样一个事实,即存在两个不同的问题 - 生成迭代模式,并根据此模式拆分数组。