倒塌numpy的阵列的所有方面,除了前两个

问题描述:

我有一个可变尺寸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, 2) 
(64, 64, 2) 
(64, 64, 2) 
(64, 64, 2) 
(64, 64, 2) 

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

不过,我首先不知道,如果顺序被保存,因为我想和是否有实现这个美好的Python的方式?

+0

你能澄清在堆叠,像样品A'':'(64,64,2,5) ','out'是哪里应该放在'out'中,输出数组是'out'? – Divakar

+0

请记住,在'numpy'中,最后一个维度是最里面的维度。如果你迭代一个(N,2,3)数组,你可以使用N(2,3)数组。 MATLAB使用相反的顺序;第一个是最内层,最外层的。语言显示3D数组的方式反映了这种顺序。 – hpaulj

重塑接受自动重新尺寸:

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

这真棒。谢谢! – Luca

编辑:正如在其他答案指出,它只是提供-1作为reshape第三维更容易。 Numpy会自动确定正确的形状。

我不确定这里的问题是什么。您可以使用np.reshape并保留订单。请看下面的代码:

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 

这完成你问什么了。

+2

尝试'.reshape(64,64,-1)';看到这个最近关于-1重塑问题:http://stackoverflow.com/questions/41776579/what-does-1-in-numpy-reshape-mean – hpaulj

+0

啊非常好。我在脑后想到有这样的事情,但不记得了。 :) –

去通过堆叠对于给定的样本(64, 64, 2, 5)的要求,我认为你需要置换的轴。对于序列改变,我们可以使用np.rollaxis,像这样 -

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:

In [235]: a = np.random.randint(11,99,(shp1)) 

In [236]: np.allclose(a, collapse_dims(a)) 
Out[236]: True 

案例#2:

In [237]: a = np.random.randint(11,99,(shp2)) 

In [238]: np.allclose(a[:,:,:,0], collapse_dims(a)[:,:,0:2]) 
Out[238]: True 

In [239]: np.allclose(a[:,:,:,1], collapse_dims(a)[:,:,2:4]) 
Out[239]: True 

In [240]: np.allclose(a[:,:,:,2], collapse_dims(a)[:,:,4:6]) # .. so on 
Out[240]: True 

案例#3:

In [241]: a = np.random.randint(11,99,(shp3)) 

In [242]: np.allclose(a, collapse_dims(a)) 
Out[242]: True 

案例#4:

In [243]: a = np.random.randint(11,99,(shp4)) 

In [244]: np.allclose(a[:,:,:,:,0].ravel(), collapse_dims(a)[:,:,:200].ravel()) 
Out[244]: True 

In [245]: np.allclose(a[:,:,:,:,1].ravel(), collapse_dims(a)[:,:,200:400].ravel()) 
Out[245]: True 

我会尽力说明@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块。

注意,当我们使用reshape会发生什么:

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×12块。你可以做任何事情来的12元行,重塑他们回到3x4的块

In [526]: arr1.reshape(2,2,3,4) 
Out[526]: 
array([[[[ 0, 1, 2, 3], 
     [ 4, 5, 6, 7], 
     ... 

但我也可能分裂的最后一维数组。 np.split可以做到这一点,但一个列表理解是比较容易理解:

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,但给出的阵列是如何连接更多的控制):

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

==========

split等效为[x[...,0] for x in np.split(arr, 4, axis=-1)]。没有索引分割会产生(2,2,3,1)数组。

collapse_dims产生(我的例子):

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

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