2016-02-05 49 views
6

所以这是一个关于重塑的使用以及这个功能如何在多维尺度上使用每个轴的问题numpy通过任意轴重塑多维数组

假设我有以下数组,其中包含由第一个索引索引的矩阵。 我想要实现的是改为索引每个矩阵的列与第一个索引。为了说明这个问题,请考虑以下示例,其中给第一个索引索引矩阵的numpy数组为z。

x = np.arange(9).reshape((3, 3)) 
y = np.arange(9, 18).reshape((3, 3)) 
z = np.dstack((x, y)).T 

其中Z是这样的:

array([[[ 0, 3, 6], 
    [ 1, 4, 7], 
    [ 2, 5, 8]], 

    [[ 9, 12, 15], 
    [10, 13, 16], 
    [11, 14, 17]]]) 

,其形状是(2, 3, 3)。这里,第一个索引是两个图像,三个三个是矩阵。

问题更具体地表述的话,是如何使用重塑,获得下述期望的输出

array([[ 0, 1, 2], 
    [ 3, 4, 5], 
    [ 6, 7, 8], 
    [ 9, 10, 11], 
    [12, 13, 14], 
    [15, 16, 17]]) 

其形状(6, 3)。这实现了数组的维度如上所示索引矩阵x和y的列。我自然倾向是直接使用在z重塑通过以下方式:

out = z.reshape(2 * 3, 3) 

但其输出是其下面的索引矩阵的行而不是列:

array([[ 0, 3, 6], 
    [ 1, 4, 7], 
    [ 2, 5, 8], 
    [ 9, 12, 15], 
    [10, 13, 16], 
    [11, 14, 17]] 

莫非重塑被用来获得上面所需的输出?或者更为一般的,当您使用重塑功能时,是否可以控制每个轴的使用方式?

两件事情:

  • 我知道如何解决这个问题。我可以穿过大矩阵(z)的每个元素进行调换,然后应用上面的方式进行重塑。这有点增加了计算时间,并且没有真正的问题。但它没有概括,它不觉得蟒蛇。所以我想知道是否有一个标准的开明的方式来做到这一点。

  • 我不清楚如何解释这个问题。如果任何人有关于如何更好地说出这个问题的建议,我都听过。

回答

7

每个数组的元素都有一个自然的(1D展平)顺序。当你重塑阵列,它是仿佛它首先压扁(从而获得自然的顺序),然​​后再成形:

In [54]: z.ravel() 
Out[54]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

In [55]: z.ravel().reshape(2*3, 3) 
Out[55]: 
array([[ 0, 3, 6], 
     [ 1, 4, 7], 
     [ 2, 5, 8], 
     [ 9, 12, 15], 
     [10, 13, 16], 
     [11, 14, 17]]) 

注意,在“自然顺序”,0和1相距甚远。但是你重塑它,0和1不会沿最后轴,这是你想要的数组中想要的东西彼此相邻:

desired = np.array([[ 0, 1, 2], 
        [ 3, 4, 5], 
        [ 6, 7, 8], 
        [ 9, 10, 11], 
        [12, 13, 14], 
        [15, 16, 17]]) 

这需要一些重新排序,在这种情况下可以这样做swapaxes

In [53]: z.swapaxes(1,2).reshape(2*3, 3) 
Out[53]: 
array([[ 0, 1, 2], 
     [ 3, 4, 5], 
     [ 6, 7, 8], 
     [ 9, 10, 11], 
     [12, 13, 14], 
     [15, 16, 17]]) 

因为swapaxes(1,2)地方所需顺序值

In [56]: z.swapaxes(1,2).ravel() 
Out[56]: 
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 
     17]) 

In [57]: desired.ravel() 
Out[57]: 
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 
     17]) 

注意,reshape方法也有一个order参数,可用于控制(C或F-)顺序,从该阵列中读取元素并放入重新整形阵列中。不过,我认为这对你的情况不利。


另一种方式去思考reshape极限是说,所有的重塑之后拉威尔是相同的:

In [71]: z.reshape(3,3,2).ravel() 
Out[71]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

In [72]: z.reshape(3,2,3).ravel() 
Out[72]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

In [73]: z.reshape(3*2,3).ravel() 
Out[73]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

In [74]: z.reshape(3*3,2).ravel() 
Out[74]: 
array([ 0, 3, 6, 1, 4, 7, 2, 5, 8, 9, 12, 15, 10, 13, 16, 11, 14, 
     17]) 

因此,如果所需的阵列的拉威尔是不同的,没有获得它的方式只是重塑。


这同样适用于与order='F'重塑,提供你还拆开与order='F'

In [109]: z.reshape(2,3,3, order='F').ravel(order='F') 
Out[109]: 
array([ 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 
     17]) 

In [110]: z.reshape(2*3*3, order='F').ravel(order='F') 
Out[110]: 
array([ 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 
     17]) 

In [111]: z.reshape(2*3,3, order='F').ravel(order='F') 
Out[111]: 
array([ 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 
     17]) 

有可能使用两个整形以获得所需的阵列:

In [83]: z.reshape(2, 3*3, order='F').reshape(2*3, 3) 
Out[83]: 
array([[ 0, 1, 2], 
     [ 3, 4, 5], 
     [ 6, 7, 8], 
     [ 9, 10, 11], 
     [12, 13, 14], 
     [15, 16, 17]]) 

但我无意中偶然发现了这个。


如果我完全误解了你的问题,xy是吉文斯(未z),那么你可以使用获得的dstackrow_stack,而不是期望的数组:

In [88]: z = np.row_stack([x, y]) 

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

不,你没有误会,你完全钉它。 x和y只是为了工作示例而构建的。我所关心的是沿着第一轴远远更大的z。 –

0

它你看dstack代码你会发现

np.dstack((x, y)).T 

是ef有趣地:

np.concatenate([i[:,:,None] for i in (x,y)],axis=2).transpose([2,1,0]) 

它重新塑造每个组件数组,然后沿着这个新的轴加入他们。最后它转换轴。

你的目标是相同的(行栈)

np.concatenate((x,y),axis=0) 
有一点逆向工程的,我们可以从 z

np.concatenate([i[...,0] for i in np.split(z.T,2,axis=2)],axis=0) 
np.concatenate([i.T[:,:,0] for i in np.split(z,2,axis=0)],axis=0) 

np.concatenate(np.split(z.T,2,axis=2),axis=0)[...,0] 

创建

所以或者使用部分转置,我们可以先保留分割和重新连接轴,然后使用concatenate

np.concatenate(z.transpose(0,2,1),axis=0) 

或其等价整形

(z.transpose(0,2,1).reshape(-1,3))