'numpy rollaxis - how exactly does it work?
So I was experimenting with numpy and I ran across a strange (?) behavior in the rollaxis method.
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)
Shouldn't the -2 reverse the rollaxis? What I'm trying to do is apply a matrix that can only be applied when the 2 coordinate is first. But then I want to put my array back into its original form. The only things which I have found to work are applying np.rollaxis(x, 2) twice, or applying np.rollaxis(x, 0, start=3). I just found these by guessing and I have no idea why they work. They also seem to be obscuring what I'm really trying to do. Could somebody please explain the way that I should 'reverse' a roll, or what I'm doing wrong?
(Is there a pythonic way to do this?)
Solution 1:[1]
np.rollaxis(tensor,axis,start) moves the axis specified by the axis parameter to the position before the axis that is located at start with no exceptions.
Say the axes are (1, 2, 3, 4, 5, 6) if axis points to the 3, and start points to the 5, then after the roll, the 3 will be just before the 5. Since the 3 in my example is at position 2 of the dimensions tuple, axis=2. Also, since the 5 is at position 4, start=4.
Like this:
>>> a.shape
(1, 2, 3, 4, 5, 6)
>>> np.rollaxis(a, 2, 4).shape
(1, 2, 4, 3, 5, 6)
As you can see, the 3 is now right before the 5. NOTE: The 3 does not move to position 4, but rather to the position before the value originally at position 4 (which in this case turns out to be position 3).
Negative numbers specify positions just like they do for lists. In other words, axis=-1 specifies the last position. In my example above there is a 6 in the -1 position and a 5 in the -2 position. Both axis and start may be negative.
You can do the same thing I did above with negative numbers like this:
>>> a.shape
(1, 2, 3, 4, 5, 6)
>>> np.rollaxis(a, -4, -2).shape
(1, 2, 4, 3, 5, 6)
If start is not specified, it defaults to 0 which is the first position. That means that if start is not specified, the specified axis will always be moved to the beginning, which is before the 1 which was originally at position 0.
If this is confusing there is another explanation that might make more sense here: Reason why numpy rollaxis is so confusing?
Solution 2:[2]
The basic idea is that it moves around the axis of the nd-array.
It takes the axis mentioned by axis parameter and puts it in the position mentioned by the start parameter; while this happens, the remaining axes in the following positions till the end will move towards right. If you ignore the start parameter, it moves the mentioned axis to the first position (i.e. it will be moved as 0th axis)
Let's understand it with an example:
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)
While moving the axis (or rolling as NumPy calls it), the already existing axis in that position makes room for the incoming axis and that and the following axes move as a block towards right side.
If you ignore the start parameter, the axis in the axis parameter will be moved to the front (i.e. to the 0th position).
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)
Comparison with 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)
Observe in the above example how np.moveaxis does circular shift while np.rollaxis just extends only towards right side.
PS: Also, note that this rollaxis operation returns a view of the input array starting from NumPy 1.10.0
Solution 3:[3]
It will have the same result when axis==start and axis == 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)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | xxx |
| Solution 2 | |
| Solution 3 | alexqinbj |
