所以这是一个关于 reshape 的使用以及该函数如何在多维尺度上使用每个轴的问题。
假设我有以下数组,其中包含由第一个索引索引的矩阵。 我想要实现的是用第一个索引代替对每个矩阵的列进行索引。为了说明这个问题,请考虑以下示例,其中给定的 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 是一个矩阵。
那么更具体的问题是如何使用 reshape 来获得以下所需的输出:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]])
形状是(6, 3)
。这实现了数组的维度索引矩阵 x 和 y 的列,如上所示。我的自然倾向是按以下方式直接在 z 上使用 reshape:
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]]
是否可以使用 reshape 来获得上述所需的输出?或者更笼统地说,当你使用reshape函数时,你能控制每个轴的使用方式吗?
两件事:
我知道如何解决这个问题。我可以通过转置大矩阵 (z) 的每个元素,然后以上述方式应用 reshape 。这会稍微增加计算时间,但问题不大。但是不泛化,没有python的感觉。所以我想知道是否有一种标准的开明方法可以做到这一点。
我不清楚如何表述这个问题。如果有人对如何更好地表达这个问题提出建议,我会洗耳恭听。
最佳答案
每个数组的元素都有一个自然的(一维扁平化)顺序。当您 reshape 数组时,它好像先被展平(从而获得自然顺序),然后再 reshape :
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 相距很远。无论您如何 reshape 它,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 的数组中。但是,我认为这对您的情况没有帮助。
考虑 reshape
限制的另一种方法是说所有 reshapes 之后的 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])
所以如果想要的数组的解法不同,就没有办法得到,只能整形。
这同样适用于使用 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]])
关于python - numpy通过任意轴 reshape 多维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35226115/