numpy通过任意轴重塑多维数组

时间:2016-02-05 14:03:51

标签: python arrays numpy matrix

所以这是关于重塑的使用以及此函数如何在多维尺度上使用每个轴的问题。

假设我有以下数组,其中包含由第一个索引索引的矩阵。 我想要实现的是使用第一个索引来索引每个矩阵的列。为了说明这个问题,请考虑下面的示例,其中给定的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)。这里,第一个索引是两个图像,三个x三个是矩阵。

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

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)的每个元素,然后以上面的方式应用重塑。这会稍微增加计算时间并且不会造成问题。但它没有概括,也没有感觉到python。所以我想知道是否有一种标准的开明方式。

  • 我不清楚如何说出这个问题。如果有人建议如何更好地说出这个问题,我全都听见了。

2 个答案:

答案 0 :(得分:10)

每个数组都有一个自然(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])

因此,如果所需数组的ravel不同,则无法获取它只是重新形成。

使用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),那么您可以使用row_stack代替{获得所需的数组{1}}:

dstack

答案 1 :(得分:0)

你看看dstack代码,你会发现

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

实际上是:

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