numpy rollaxis - 它是如何工作的?

15 投票
4 回答
15770 浏览
提问于 2025-04-17 23:27

我在玩numpy的时候,发现了rollaxis方法有点奇怪的行为。

In [81]: a = np.ones((4, 3, 2))

In [82]: a.shape
Out[82]: (4, 3, 2)

In [83]: x = np.rollaxis(a, 2)

In [84]: x.shape
Out[84]: (2, 4, 3)

In [85]: np.rollaxis(x, -2).shape
Out[85]: (4, 2, 3)

难道-2不是应该反转rollaxis吗?我想做的是应用一个只能在第二个坐标为首的矩阵。但之后我又想把我的数组恢复到原来的样子。我发现只有两种方法有效:要么是把np.rollaxis(x, 2)这个操作做两次,要么是用np.rollaxis(x, 0, start=3)。这些都是我凭猜测找到的,我也不知道为什么它们有效。而且它们似乎还掩盖了我真正想做的事情。有人能解释一下我应该怎么“反转”这个roll,或者我哪里做错了吗?

(有没有更pythonic的做法?)

4 个回答

0

当轴等于起始值(start)和轴等于起始值减一(start-1)时,结果是一样的。

>>>a=np.ones([1, 2, 3, 4, 5, 6])
(1, 2, 3, 4, 5, 6)
>>> np.rollaxis(a, axis=2, start=2).shape
(1, 2, 3, 4, 5, 6)
>>> np.rollaxis(a, axis=2, start=3).shape
(1, 2, 3, 4, 5, 6)
0

这个基本的想法是,它在多维数组的轴上移动。它会根据axis参数指定的轴,把这个轴放到start参数指定的位置;在这个过程中,后面的轴会向右移动。如果你不考虑start参数,它会把指定的轴移动到第一个位置(也就是变成第0轴)。

我们用一个例子来理解一下:

In [21]: arr = np.ones((3,4,5,6))

In [22]: arr.shape
Out[22]: (3, 4, 5, 6)
# here 0th axis is 3, 1st axis is 4, 2nd axis is 5, 3rd axis is 6

# moving `3`rd axis as `1`st axis
In [27]: np.rollaxis(arr, 3, 1).shape

# see how `6` which was the third axis has been moved to location `1`
Out[27]: (3, 6, 4, 5)

在移动轴的时候(NumPy称之为滚动),原本在那个位置的轴会为新来的轴腾出空间,接下来的轴就像一个整体一样向右移动。

如果你不考虑start参数,axis参数中的轴会被移动到最前面(也就是第0位置)。

In [29]: a.shape
Out[29]: (3, 4, 5, 6)

# ignoring the `start` moves the axis to the very front position.
In [30]: np.rollaxis(arr, 3).shape
Out[30]: (6, 3, 4, 5)

np.moveaxis的比较

In [38]: arr.shape
Out[38]: (3, 4, 5, 6)

In [39]: np.rollaxis(arr, 0, -1).shape
Out[39]: (4, 5, 3, 6)

In [40]: np.moveaxis(arr, 0, -1).shape
Out[40]: (4, 5, 6, 3)

在上面的例子中,可以看到np.moveaxis是如何进行循环移动的,而np.rollaxis只是简单地向右扩展。


另外要注意的是,从NumPy 1.10.0开始,这个rollaxis操作返回的是输入数组的一个视图

8

np.rollaxis(tensor, axis, start) 这个函数的作用是把你指定的轴(axis)移动到另一个轴(start)之前,整个过程没有任何例外。

假设你的轴是 (1, 2, 3, 4, 5, 6),如果你把轴设置为3,而把开始位置设置为5,那么在移动之后,3就会出现在5的前面。根据我的例子,3在维度元组中的位置是2,所以 axis=2。而5在位置4,所以 start=4

就像这样:

>>> a.shape

(1, 2, 3, 4, 5, 6)

>>> np.rollaxis(a, 2, 4).shape

(1, 2, 4, 3, 5, 6)

你可以看到,3现在就在5的前面。注意:3并不是移动到位置4,而是移动到原本在位置4的值之前的位置(在这个例子中是位置3)。

负数也可以用来指定位置,就像在列表中一样。换句话说,axis=-1 表示最后一个位置。在我上面的例子中,-1位置是6,-2位置是5。axis和start都可以是负数。

你也可以用负数来做我上面做的事情,像这样:

>>> a.shape

(1, 2, 3, 4, 5, 6)

>>> np.rollaxis(a, -4, -2).shape

(1, 2, 4, 3, 5, 6)

如果没有指定start,它默认是0,也就是第一个位置。这意味着如果没有指定start,指定的轴总是会被移动到最前面,也就是在原本在位置0的1之前。

如果这让你感到困惑,这里有另一个解释可能更容易理解: 为什么numpy的rollaxis会让人感到困惑?

19

方法 rollaxis

def rollaxis(a, axis, start=0):

是用来重新安排你选择的 axisstart 的“位置”

根据你的例子:

a = np.ones((4, 3, 2))
x = np.rollaxis(a, 2)
# x.shape = (2, 4, 3)

关于形状:rollaxis 会把数字 2(在你的最后一个 axis=2 中)移动到第一个位置,因为 start=0

通过使用

x2 = np.rollaxis(x, -2)
# x2.shape = (4,2,3)

rollaxis 会把数字 4(这是倒数第二个轴,axis=-2)移动到第一个位置,因为 start=0。这就解释了你的结果 (4,2,3),而不是 (4,3,2)

按照同样的逻辑,这也解释了为什么应用 rollaxis(a,2) 两次会让数组的形状回到最初的样子。np.rollaxis(x, 0, start=3) 也能正常工作,因为第一个轴会变成最后一个轴,换句话说,(2,4,3) 中的数字 2 会移动到最后的位置,结果变成 (4,3,2)。

撰写回答