【问题标题】:Reshape of set of arrays in 3D array重塑 3D 数组中的数组集
【发布时间】:2014-12-27 21:26:13
【问题描述】:

为了进行计算,我有一组数组:“子”数组(如下所示),我想将其重塑为“测试”数组给出的数组:

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)])

【问题讨论】:

  • 它必须是自动化的,因为数组对我来说非常重要:/
  • 当子数组不是很重要时,它似乎工作......但并非在所有情况下:/
  • “我有一些错误......”。愿意与我们分享吗?
  • 感谢您的帮助 ;) 首先我想说(对于一些错误)当我在子数组的大小或要分解的数组上播放时,我会重新整形并且一些子数组没有很好地放置......然后,我需要自动化代码,因为我的数组是 400x250...:s

标签: python arrays numpy reshape


【解决方案1】:

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

>>> 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

【讨论】:

  • 您的解决方案与 sub.shape 完美配合,这正是 OP 提出的 (2,4,2,2),因此它们都解决了 OP 问题。是否可以概括/参数化您的一种解决方案以使用 (m,4,r,c) -> (m,2*r,2*c) 类型的 4D -> 3D 转换?
  • 嗨@gboffi - 我怀疑可以使切片适应更一般的情况,但可能需要对我建议的方法进行一些修改。我还没有尝试过,但如果我成功了,我会尝试更新我的答案。
【解决方案2】:

也许存在一个纯粹的 numpy 解决方案,但我不知道它会使用相当多的技巧。因此,下面的解决方案效率不高,因为它使用 python 的 for 循环(使其速度变慢),但它会以 general 的方式得到你的结果,所以没有它取决于你的大小实际的 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】:
    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)类型的不同形状,上面的代码可以适应不同的需求。

    最后我想补充一点,当您查看代码时您会真正看到代码正在实现什么,这可能会在效率方面补偿代码的其他缺陷(即,复制与重塑)。


    更好的解决方案(即不是我的 ;-) 和一些事后的想法

    我发现this answer from unutbu(包含指向更通用解决方案的链接)OP 可以轻松(?)适应她/他的需求。由于复杂的重塑 然而,所涉及的数据被复制,因此 OP 可能希望测量这两种方法的不同性能,同时考虑到她/他的程序总运行时间的“重塑”的发生率(即恕我直言,在2' 的运行时间不值得努力)

    示例交互会话

    在下文中,数据和过程字面意思来自 the above mentioned answer from unutbu,最后两条语句是我添加的,用来显示ndarrays、xyz这三个数据缓冲区的地址。

    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]: 
    

    【讨论】:

    • ps:它适用于数组subs 中任意数量的“顶部”元素,这里唯一的假设是如何组织堆叠,但您应该能够编写概括我的 ad hoc 实施
    • 嗨@gboffi!以后如果你需要为自己的答案写一个 PS,请随时将其放入答案的正文中。这使它更容易保持焦点,因为人们可能会跳过 cmets。
    【解决方案4】:

    这可以使用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)
    

    【讨论】:

      猜你喜欢
      • 2016-02-10
      • 2023-04-05
      • 2017-09-18
      • 2020-04-22
      • 1970-01-01
      • 2017-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多