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)
。在这里,第一个索引是两个图像,三个x 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)的每个元素,然后按照上述方式应用整形。这会稍微增加计算时间,并且并不是真正的问题。但是它不能一概而论,也不会感觉到python。所以我想知道是否有一种标准的开明方式来做到这一点。
-
我不清楚如何表达这个问题。如果有人对如何更好地表达这个问题有任何建议,我将不胜感激。
问题答案:
每个数组的元素都有自然的顺序(一维展平)。当您对数组进行整形时,就 好像先 对其进行了展平(从而获得自然顺序),然后对其进行了整形:
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]])
但我偶然发现了这一点。
如果我完全误解了您的问题,x
并且y
是给定值(不是z
),则可以使用row_stack
而不是获得所需的数组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]])