Python 通过任意轴对多维阵列进行numpy整形

Python 通过任意轴对多维阵列进行numpy整形,python,arrays,numpy,matrix,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

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

假设我有以下数组,其中包含由第一个索引索引的矩阵我想要实现的是用第一个索引为每个矩阵的列编制索引。为了说明这个问题,考虑下面的例子,其中用第一个索引来索引矩阵的给定的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。所以我想知道是否有一个标准的开明方式来做这件事

  • 我不清楚如何表达这个问题。如果有人对如何更好地表达这个问题提出建议,我洗耳恭听

每个数组对其元素都有一个自然的(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]])
这需要一些重新排序,在这种情况下,可以通过
swapax

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])
请注意,
reformate
方法还有一个
order
参数,可用于控制从数组中读取元素并将其放置在重塑数组中的(C-或F-)顺序。然而,我认为这对你的情况没有帮助


思考
重塑
限制的另一种方式是说,ravel后面的所有重塑都是相同的:

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]])
但我意外地发现了这一点


如果我完全误解了您的问题,并且
x
y
是给定的(而不是
z
),那么您可以使用
行堆栈
而不是
dstack
)获得所需的数组:

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

如果您查看
dstack
code,您会发现

np.dstack((x, y)).T
实际上:

np.concatenate([i[:,:,None] for i in (x,y)],axis=2).transpose([2,1,0])
它重塑每个组件阵列的形状,然后沿此新轴连接它们。最后,它转换轴

您的目标与(行堆栈)相同

因此,通过一点逆向工程,我们可以使用

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(z.transpose(0,2,1),axis=0)
或其重塑等效物

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

不,你没有误解,你完全搞定了。x和y,其中仅为工作示例构造。我关心的是一个z,它沿着第一个轴要大得多。
np.concatenate(z.transpose(0,2,1),axis=0)
(z.transpose(0,2,1).reshape(-1,3))