重塑3D数组中的数组集

时间:2014-10-31 14:11:39

标签: python arrays numpy reshape

为了进行计算,我有一组数组:" sub"数组(如下所示),我希望将其重新整形为数组,如#34; test"阵列:

import numpy as np

sub = np.array([[[[ 1.,  1.],
         [ 1.,  1.]],

        [[ 2.,  2.],
         [ 2.,  2.]],

        [[ 3.,  3.],
         [ 3.,  3.]],

        [[ 4.,  4.],
         [ 4.,  4.]]],

       [[[ 5.,  5.],
         [ 5.,  5.]],

        [[ 6.,  6.],
         [ 6.,  6.]],

        [[ 7.,  7.],
         [ 7.,  7.]],

        [[ 8.,  8.],
         [ 8.,  8.]]]])


test=np.array([[[ 1.,  1.,  2., 2.],
        [ 1.,  1.,  2., 2.],
        [ 3.,  3.,  4., 4.],
        [ 3.,  3.,  4., 4.]],

       [[ 5.,  5.,  6., 6.],
        [ 5.,  5.,  6., 6.],
        [ 7.,  7.,  8., 8.],
        [ 7.,  7.,  8., 8.]]]) 

我在帖子上发现了一些似乎适用于我的案例的代码,但我有一些错误......

k,l,m,n,p =2,2,2,2,2
conc = np.array([np.ones([p,m,n],dtype=int)*i for i in range(k*l)])
test_reshape=np.vstack([np.hstack(sub[i:i+l]) for i in range(0,k*l*p,l)])

4 个答案:

答案 0 :(得分:2)

这是将数组交换,切片和堆叠成形状的另一种方法:

>>> t = sub.swapaxes(1, 3).T.swapaxes(1, 3)
>>> x = np.c_[t[::2, 0], t[1::2, 0]]
>>> y = np.c_[t[::2, 1], t[1::2, 1]]
>>> np.array((np.r_[x[0], x[1]], np.r_[y[0], y[1]]))

array([[[ 1.,  1.,  2.,  2.],
        [ 1.,  1.,  2.,  2.],
        [ 3.,  3.,  4.,  4.],
        [ 3.,  3.,  4.,  4.]],

       [[ 5.,  5.,  6.,  6.],
        [ 5.,  5.,  6.,  6.],
        [ 7.,  7.,  8.,  8.],
        [ 7.,  7.,  8.,  8.]]])

修改:或者,挤压,切片和堆叠:

>>> x = np.c_[sub[:1][:,::2], sub[:1][:,1::2]].squeeze()
>>> y = np.c_[sub[1:][:,::2], sub[1:][:,1::2]].squeeze()
>>> np.array((np.r_[x[0], x[1]], np.r_[y[0], y[1]]))
# the required array

答案 1 :(得分:1)

import numpy as np
sub = np.array(...)
test = np.array([np.hstack((np.vstack(( s[0],s[1] )),
                            np.vstack(( s[2],s[3] )))) for s in sub])
print test

在OP的示例中,sub的形状为(2,4,2,2),但上面的代码对于形状为(n,4,m,m)的数组而言一样。对于(n,k,m,m)类型的不同形状,上面的代码可以适应不同的要求。

最后我想补充一点,当您查看代码时,您会看到代码所实现的内容,这可能会在效率方面补偿代码的其他缺陷(即复制vs reshaping)。


一个更好的解决方案(即,不是我的;-)和一些后期

我发现this answer from unutbu(其中包含指向更一般解决方案的链接)OP可以轻松(?)适应她/他的需求。由于复杂的重塑是 然而,所涉及的数据被复制,因此OP可能想要测量两种方法的不同表现,同时考虑到“重塑”她/他的程序的总运行时间的发生率(即,imho剃须0.3s)运行时2'不值得努力)

示例交互式会话

在下文中,数据和程序字面上取消 the above mentioned answer from unutbu,我添加的最后两个语句用于显示三个ndarrayxyz的数据缓冲区的地址。

In [1]: import numpy as np

In [2]: x = np.arange(16).reshape((4,2,2))

In [3]: y = x.reshape(2,2,2,2).swapaxes(1,2).reshape(4,-1)

In [4]: x
Out[4]: 
array([[[ 0,  1],
        [ 2,  3]],

       [[ 4,  5],
        [ 6,  7]],

       [[ 8,  9],
        [10, 11]],

       [[12, 13],
        [14, 15]]])

In [5]: y
Out[5]: 
array([[ 0,  1,  4,  5],
       [ 2,  3,  6,  7],
       [ 8,  9, 12, 13],
       [10, 11, 14, 15]])

In [6]: z = x.T

In [7]: [a.__array_interface__['data'][0] for a in (x, y, z)]
Out[7]: [46375856, 45578800, 46375856]

In [8]: 

答案 2 :(得分:1)

也许存在一个纯粹的numpy解决方案,但我并没有意识到它,并且它会大步使用相当多的技巧。因此下面的解决方案效率不高,因为它使用python进行循环(使其不那么快),但它会以一般的方式获得结果,所以没有它取决于您实际的4D阵列的大小。

np.vstack( (sub[vol,2*sheet:2*sheet+2].reshape((4,-1)).T for vol in range(2) for sheet in range(2))).reshape((2,4,-1)

答案 3 :(得分:1)

可以使用a reshape/swapaxes trick

完成此操作
In [92]: sub.reshape(2,2,2,2,2).swapaxes(2,3).reshape(test.shape)
Out[92]: 
array([[[ 1.,  1.,  2.,  2.],
        [ 1.,  1.,  2.,  2.],
        [ 3.,  3.,  4.,  4.],
        [ 3.,  3.,  4.,  4.]],

       [[ 5.,  5.,  6.,  6.],
        [ 5.,  5.,  6.,  6.],
        [ 7.,  7.,  8.,  8.],
        [ 7.,  7.,  8.,  8.]]])

In [94]: np.allclose(sub.reshape(2,2,2,2,2).swapaxes(2,3).reshape(test.shape), test)
Out[94]: True

我承认我不知道如何在没有猜测的情况下生成这种解决方案。但是看起来当你想要重新排列数组中的“块”时,有一种方法可以通过重新整形到更高的维度,交换某些轴,然后重新整形到所需的形状来实现。鉴于sub.shape (2, 4, 2, 2)重塑为更高维度,必须表示(2, 2, 2, 2, 2)。因此,您只需要测试表单

的解决方案
sub.reshape(2,2,2,2,2).swapaxes(i,j).reshape(test.shape)

这很容易做到:

for i,j in IT.combinations(range(5), 2):
    if np.allclose(sub.reshape(2,2,2,2,2).swapaxes(i,j).reshape(test.shape), test):
       print(i,j)

显示要交换的右轴:

(2, 3)