Python 折叠numpy数组的所有维度(前两个除外)

Python 折叠numpy数组的所有维度(前两个除外),python,numpy,Python,Numpy,我有一个可变维numpy数组,例如,它可以有以下形状 (64, 64) (64, 64, 2, 5) (64, 64, 40) (64, 64, 10, 20, 4) 我想做的是,如果维度的数量大于3,我想在保持秩序的同时,将所有其他维度折叠/堆叠到第三维中。因此,在我上面的示例中,操作后的形状应为: (64, 64) (64, 64, 10) (64, 64, 40) (64, 64, 800) 此外,还需要保持秩序。例如,形状(64,64,2,5)的数组应按以下方式堆叠: (64, 64

我有一个可变维numpy数组,例如,它可以有以下形状

(64, 64)
(64, 64, 2, 5)
(64, 64, 40)
(64, 64, 10, 20, 4)
我想做的是,如果维度的数量大于3,我想在保持秩序的同时,将所有其他维度折叠/堆叠到第三维中。因此,在我上面的示例中,操作后的形状应为:

(64, 64)
(64, 64, 10)
(64, 64, 40)
(64, 64, 800)
此外,还需要保持秩序。例如,形状
(64,64,2,5)
的数组应按以下方式堆叠:

(64, 64, 2)
(64, 64, 2)
(64, 64, 2)
(64, 64, 2)
(64, 64, 2)
i、 e.一个接一个的3D切片。此外,手术后,我希望将其重塑为原始形状,而不进行任何排列,即保持原始顺序

我可以做的一个方法是将所有维度值从3乘以最后一个维度,即

shape = array.shape
if len(shape) > 3:
    final_dim = 1
    for i in range(2, len(shape)):
        final_dim *= shape[i]
然后重塑阵列的形状。比如:

array.reshape(64, 64, final_dim)

然而,我首先不确定是否按照我的意愿保留了顺序,以及是否有更好的pythonic方法来实现这一点?

编辑:正如其他答案中所指出的那样,只提供-1作为
重塑的第三维更加容易。然后,Numpy会自动确定正确的形状

我不确定这里的问题是什么。您只需使用
np.重塑
即可保持顺序。请参阅以下代码:

import numpy as np

A = np.random.rand(20,20,2,2,18,5)
print A.shape

new_dim = np.prod(A.shape[2:])
print new_dim
B = np.reshape(A, (A.shape[0], A.shape[1], np.prod(A.shape[2:])))
print B.shape

C = B.reshape((20,20,2,2,18,5))
print np.array_equal(A,C)
输出为:

(20L, 20L, 2L, 2L, 18L, 5L)
360
(20L, 20L, 360L)
True

这完全满足了您的要求。

重塑接受自动重新标注:

a=rand(20,20,8,6,4)
s=a.shape[:2]
if a.ndim>2 : s = s+ (-1,)
b=a.reshape(s)

根据给定
(64,64,2,5)
样本的堆叠要求,我认为您需要排列轴。对于排列,我们可以使用-

def collapse_dims(a):
    if a.ndim>3:
        return np.rollaxis(a,-1,2).reshape(a.shape[0],a.shape[1],-1)
    else:
        return a
在给定的四个示例形状上运行示例-

1) 示例形状:

In [234]: shp1 = (64, 64)
     ...: shp2 = (64, 64, 2, 5)
     ...: shp3 = (64, 64, 40)
     ...: shp4 = (64, 64, 10, 20, 4)
     ...: 
案例1:

案例2:

案例3:

案例4:


我将试图说明
@Divaker
带来的担忧

In [522]: arr = np.arange(2*2*3*4).reshape(2,2,3,4)
In [523]: arr
Out[523]: 
array([[[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]],

        [[12, 13, 14, 15],
         [16, 17, 18, 19],
         [20, 21, 22, 23]]],


       [[[24, 25, 26, 27],
         [28, 29, 30, 31],
         [32, 33, 34, 35]],

        [[36, 37, 38, 39],
         [40, 41, 42, 43],
         [44, 45, 46, 47]]]])
4是最内部的维度,因此它将数组显示为3x4块。如果你注意空格和[],你会看到有2x2个街区

注意当我们使用
重塑时会发生什么:

In [524]: arr1 = arr.reshape(2,2,-1)
In [525]: arr1
Out[525]: 
array([[[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
        [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]],

       [[24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35],
        [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]]])
现在是2个2x12街区。您可以对这12个元素行执行任何操作,并将它们重新整形为3x4块

In [526]: arr1.reshape(2,2,3,4)
Out[526]: 
array([[[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
      ...
但我也可以在最后一个维度上拆分这个数组<代码>np.拆分
可以做到,但列表理解更容易理解:

In [527]: alist = [arr[...,i] for i in range(4)]
In [528]: alist
Out[528]: 
[array([[[ 0,  4,  8],
         [12, 16, 20]],

        [[24, 28, 32],
         [36, 40, 44]]]), 
 array([[[ 1,  5,  9],
         [13, 17, 21]],

        [[25, 29, 33],
         [37, 41, 45]]]), 
 array([[[ 2,  6, 10],
         [14, 18, 22]],

        [[26, 30, 34],
         [38, 42, 46]]]), 
 array([[[ 3,  7, 11],
         [15, 19, 23]],

        [[27, 31, 35],
         [39, 43, 47]]])]
它包含4(2,2,3)个数组。请注意,3个元素行在4d显示中显示为列

我可以使用
np.stack
(类似于
np.array
,但可以更好地控制阵列的连接方式)将其改造为4d阵列:

==========

split
等价物是np.split(arr,4,axis=-1)中x的
[x[…,0]
。如果不使用索引拆分,将生成(2,2,3,1)个数组

collapse\u dims
产生(例如:

一个(2,2,12)数组,但元素的行顺序不同。在展平之前,它在内部2维上进行转置

In [535]: arr[0,0,:,:].ravel()
Out[535]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
In [536]: arr[0,0,:,:].T.ravel()
Out[536]: array([ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11])
恢复到原来的顺序需要再次滚动或转置

In [542]: arr2.reshape(2,2,4,3).transpose(0,1,3,2)
Out[542]: 
array([[[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]],

      ....

        [[36, 37, 38, 39],
         [40, 41, 42, 43],
         [44, 45, 46, 47]]]])

尝试
。重塑(64,64,-1)
;看看最近关于重塑中-1的问题:啊,很好。我暗自以为有这样的事,但记不得了你能澄清一下堆叠的问题吗,比如对于样本
a
(64,64,2,5)
a[:,:,:,0]
应该放在哪里
out
,并且
out
是输出数组吗?请记住,在
numpy
中,最后一个维度是最内部的维度。如果迭代(N,2,3)数组,则使用N(2,3)数组。MATLAB采用反序;第一个是最里面的,最后一个是最外面的。语言显示3d数组的方式反映了这种顺序。这太棒了。非常感谢。
In [526]: arr1.reshape(2,2,3,4)
Out[526]: 
array([[[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
      ...
In [527]: alist = [arr[...,i] for i in range(4)]
In [528]: alist
Out[528]: 
[array([[[ 0,  4,  8],
         [12, 16, 20]],

        [[24, 28, 32],
         [36, 40, 44]]]), 
 array([[[ 1,  5,  9],
         [13, 17, 21]],

        [[25, 29, 33],
         [37, 41, 45]]]), 
 array([[[ 2,  6, 10],
         [14, 18, 22]],

        [[26, 30, 34],
         [38, 42, 46]]]), 
 array([[[ 3,  7, 11],
         [15, 19, 23]],

        [[27, 31, 35],
         [39, 43, 47]]])]
In [529]: np.stack(alist, axis=-1)
Out[529]: 
array([[[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]],
         ...
        [[36, 37, 38, 39],
         [40, 41, 42, 43],
         [44, 45, 46, 47]]]])
In [532]: np.rollaxis(arr,-1,2).reshape(arr.shape[0],arr.shape[1],-1)
Out[532]: 
array([[[ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11],
        [12, 16, 20, 13, 17, 21, 14, 18, 22, 15, 19, 23]],

       [[24, 28, 32, 25, 29, 33, 26, 30, 34, 27, 31, 35],
        [36, 40, 44, 37, 41, 45, 38, 42, 46, 39, 43, 47]]])
In [535]: arr[0,0,:,:].ravel()
Out[535]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
In [536]: arr[0,0,:,:].T.ravel()
Out[536]: array([ 0,  4,  8,  1,  5,  9,  2,  6, 10,  3,  7, 11])
In [542]: arr2.reshape(2,2,4,3).transpose(0,1,3,2)
Out[542]: 
array([[[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]],

      ....

        [[36, 37, 38, 39],
         [40, 41, 42, 43],
         [44, 45, 46, 47]]]])