Hi Numpy Folks, A while back, I filed this ticket: http://projects.scipy.org/numpy/ticket/1441 suggesting a change to rollaxis() and some fixes to the doc and error reporting. Ralf Gommers suggested I float the behavior change here, so that's what I'm doing.
The motivation for the change comes because it seems like there should be a simpler way to get some axis into the last position than to do this:
a = np.ones((3,4,5,6)) b = np.rollaxis(a, axis=0, start=len(a.shape)) b.shape
(4, 5, 6, 3)
But currently it seems there isn't because when you specify -1 as the 'start' argument, the axis is moved into the second-to-last position. My proposed change, which you can see on the ticket, would change that so that using -1 referred to the end position. Note that the use of negative 'start' arguments isn't currently documented and, in its current form, doesn't seem very useful. My proposal wouldn't change the behavior for positive 'start' values at all, and the interpretation of 'axis' arguments is also unaffected.
If that's going to break too much code, here's a pathway that might be acceptable: Add a new function moveaxis() which works the way rollaxis() does for positive arguments but in the new way for negative arguments. Eventually, rollaxis could be deprecated to keep things tidy. This has the added advantage of using a name that seems to fit what the function does better - 'rollaxis' suggests a behavior like the roll() function which affects other axes, which isn't what happens.
Thanks for listening; I'm a big fan of Numpy.
Best, Ken Basye
Hi Ken,
This is a tricky one. The current behaviour of rollaxis is to remove the requested axis from the list of axes and then insert it before the axis specified. This is exactly how python's list insertion works:
In [1]: a = range(10)
In [3]: a.insert(-1,'a')
In [4]: a Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 9]
And indeed, there's no clean way to add something to the end of a list using insert (apart from the obvious a.insert(len(a),'b') ). For this you have .append(). Unfortunately numpy's rollaxis, while it agrees with insert in its behaviour, doesn't have a move_axis_to_end. The situation is also somewhat muddied by the fact that rollaxis also removes the axis from the original list of axes, so that the interpretation of index numbers is a little more subtle. But I think your suggested behaviour would be confusing because of the conflict with python's insert. How about allowing the string "end" as an argument to rollaxis to specify that the axis should go at the end?
Anne
On 21 September 2010 15:48, Ken Basye kbasye1@jhu.edu wrote:
Hi Numpy Folks, A while back, I filed this ticket: http://projects.scipy.org/numpy/ticket/1441 suggesting a change to rollaxis() and some fixes to the doc and error reporting. Ralf Gommers suggested I float the behavior change here, so that's what I'm doing.
The motivation for the change comes because it seems like there should be a simpler way to get some axis into the last position than to do this:
>>> a = np.ones((3,4,5,6)) >>> b = np.rollaxis(a, axis=0, start=len(a.shape)) >>> b.shape (4, 5, 6, 3)
But currently it seems there isn't because when you specify -1 as the 'start' argument, the axis is moved into the second-to-last position. My proposed change, which you can see on the ticket, would change that so that using -1 referred to the end position. Note that the use of negative 'start' arguments isn't currently documented and, in its current form, doesn't seem very useful. My proposal wouldn't change the behavior for positive 'start' values at all, and the interpretation of 'axis' arguments is also unaffected.
If that's going to break too much code, here's a pathway that might be acceptable: Add a new function moveaxis() which works the way rollaxis() does for positive arguments but in the new way for negative arguments. Eventually, rollaxis could be deprecated to keep things tidy. This has the added advantage of using a name that seems to fit what the function does better - 'rollaxis' suggests a behavior like the roll() function which affects other axes, which isn't what happens.
Thanks for listening; I'm a big fan of Numpy.
Best, Ken Basye
NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
On Wed, Sep 22, 2010 at 4:14 AM, Anne Archibald aarchiba@physics.mcgill.cawrote:
Hi Ken,
This is a tricky one. The current behaviour of rollaxis is to remove the requested axis from the list of axes and then insert it before the axis specified. This is exactly how python's list insertion works:
In [1]: a = range(10)
In [3]: a.insert(-1,'a')
In [4]: a Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 9]
And indeed, there's no clean way to add something to the end of a list using insert (apart from the obvious a.insert(len(a),'b') ). For this you have .append(). Unfortunately numpy's rollaxis, while it agrees with insert in its behaviour, doesn't have a move_axis_to_end. The situation is also somewhat muddied by the fact that rollaxis also removes the axis from the original list of axes, so that the interpretation of index numbers is a little more subtle. But I think your suggested behaviour would be confusing because of the conflict with python's insert. How about allowing the string "end" as an argument to rollaxis to specify that the axis should go at the end?
Allowing "end" is an easy solution, but note that moving an axis to the end is already possible:
a = np.ones((3,4,5,6)) np.rollaxis(a, 2, len(a)+1).shape # roll axis to to last position
(3, 4, 6, 5)
Not consistent with insert though, there you would use len(a) instead of len(a)+1. It's a little ugly, but perhaps just documenting this is no worse than allowing a string or adding yet another function.
Ralf
Anne
On 21 September 2010 15:48, Ken Basye kbasye1@jhu.edu wrote:
Hi Numpy Folks, A while back, I filed this ticket: http://projects.scipy.org/numpy/ticket/1441 suggesting a change to rollaxis() and some fixes to the doc and error reporting. Ralf Gommers suggested I float the behavior change here, so that's what I'm doing.
The motivation for the change comes because it seems like there should be a simpler way to get some axis into the last position than to do this:
a = np.ones((3,4,5,6)) b = np.rollaxis(a, axis=0, start=len(a.shape)) b.shape
(4, 5, 6, 3)
But currently it seems there isn't because when you specify -1 as the 'start' argument, the axis is moved into the second-to-last position. My proposed change, which you can see on the ticket, would change that so that using -1 referred to the end position. Note that the use of negative 'start' arguments isn't currently documented and, in its current form, doesn't seem very useful. My proposal wouldn't change the behavior for positive 'start' values at all, and the interpretation of 'axis' arguments is also unaffected.
If that's going to break too much code, here's a pathway that might be acceptable: Add a new function moveaxis() which works the way rollaxis() does for positive arguments but in the new way for negative arguments. Eventually, rollaxis could be deprecated to keep things tidy. This has the added advantage of using a name that seems to fit what the function does better - 'rollaxis' suggests a behavior like the roll() function which affects other axes, which isn't what happens.
Thanks for listening; I'm a big fan of Numpy.
Best, Ken Basye
NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
On Thu, Sep 23, 2010 at 12:20 AM, Ralf Gommers ralf.gommers@googlemail.comwrote:
On Wed, Sep 22, 2010 at 4:14 AM, Anne Archibald < aarchiba@physics.mcgill.ca> wrote:
Hi Ken,
This is a tricky one. The current behaviour of rollaxis is to remove the requested axis from the list of axes and then insert it before the axis specified. This is exactly how python's list insertion works:
In [1]: a = range(10)
In [3]: a.insert(-1,'a')
In [4]: a Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 9]
And indeed, there's no clean way to add something to the end of a list using insert (apart from the obvious a.insert(len(a),'b') ). For this you have .append(). Unfortunately numpy's rollaxis, while it agrees with insert in its behaviour, doesn't have a move_axis_to_end. The situation is also somewhat muddied by the fact that rollaxis also removes the axis from the original list of axes, so that the interpretation of index numbers is a little more subtle. But I think your suggested behaviour would be confusing because of the conflict with python's insert. How about allowing the string "end" as an argument to rollaxis to specify that the axis should go at the end?
Allowing "end" is an easy solution, but note that moving an axis to the end is already possible:
a = np.ones((3,4,5,6)) np.rollaxis(a, 2, len(a)+1).shape # roll axis to to last position
(3, 4, 6, 5)
Not consistent with insert though, there you would use len(a) instead of len(a)+1. It's a little ugly, but perhaps just documenting this is no worse than allowing a string or adding yet another function.
It is a common enough operation that it would be nice to have a less cumbersome way to specify it.
Chuck
On 23 September 2010 02:20, Ralf Gommers ralf.gommers@googlemail.com wrote:
On Wed, Sep 22, 2010 at 4:14 AM, Anne Archibald aarchiba@physics.mcgill.ca wrote:
Hi Ken,
This is a tricky one. The current behaviour of rollaxis is to remove the requested axis from the list of axes and then insert it before the axis specified. This is exactly how python's list insertion works:
In [1]: a = range(10)
In [3]: a.insert(-1,'a')
In [4]: a Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 9]
And indeed, there's no clean way to add something to the end of a list using insert (apart from the obvious a.insert(len(a),'b') ). For this you have .append(). Unfortunately numpy's rollaxis, while it agrees with insert in its behaviour, doesn't have a move_axis_to_end. The situation is also somewhat muddied by the fact that rollaxis also removes the axis from the original list of axes, so that the interpretation of index numbers is a little more subtle. But I think your suggested behaviour would be confusing because of the conflict with python's insert. How about allowing the string "end" as an argument to rollaxis to specify that the axis should go at the end?
Allowing "end" is an easy solution, but note that moving an axis to the end is already possible:
a = np.ones((3,4,5,6)) np.rollaxis(a, 2, len(a)+1).shape # roll axis to to last position
(3, 4, 6, 5)
Not consistent with insert though, there you would use len(a) instead of len(a)+1. It's a little ugly, but perhaps just documenting this is no worse than allowing a string or adding yet another function.
Just a quick correction: len(a) gives a.shape[0], while what you want is actually len(a.shape). So:
In [1]: a = np.zeros((2,3,4,5,6))
In [2]: len(a) Out[2]: 2
In [8]: np.rollaxis(a,0,len(a.shape)).shape Out[8]: (3, 4, 5, 6, 2)
So it behaves just like insert. But "len(a.shape)" is rather cumbersome, especially if you haven't given a a name yet:
d = (a+b*c).rollaxis(2,'end')
Anne
Ralf
Anne
On 21 September 2010 15:48, Ken Basye kbasye1@jhu.edu wrote:
Hi Numpy Folks, A while back, I filed this ticket: http://projects.scipy.org/numpy/ticket/1441 suggesting a change to rollaxis() and some fixes to the doc and error reporting. Ralf Gommers suggested I float the behavior change here, so that's what I'm doing.
The motivation for the change comes because it seems like there should be a simpler way to get some axis into the last position than to do this:
>>> a = np.ones((3,4,5,6)) >>> b = np.rollaxis(a, axis=0, start=len(a.shape)) >>> b.shape (4, 5, 6, 3)
But currently it seems there isn't because when you specify -1 as the 'start' argument, the axis is moved into the second-to-last position. My proposed change, which you can see on the ticket, would change that so that using -1 referred to the end position. Note that the use of negative 'start' arguments isn't currently documented and, in its current form, doesn't seem very useful. My proposal wouldn't change the behavior for positive 'start' values at all, and the interpretation of 'axis' arguments is also unaffected.
If that's going to break too much code, here's a pathway that might be acceptable: Add a new function moveaxis() which works the way rollaxis() does for positive arguments but in the new way for negative arguments. Eventually, rollaxis could be deprecated to keep things tidy. This has the added advantage of using a name that seems to fit what the function does better - 'rollaxis' suggests a behavior like the roll() function which affects other axes, which isn't what happens.
Thanks for listening; I'm a big fan of Numpy.
Best, Ken Basye
NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
On Thu, Sep 23, 2010 at 10:32 AM, Anne Archibald aarchiba@physics.mcgill.ca wrote:
Just a quick correction: len(a) gives a.shape[0], while what you want is actually len(a.shape). So:
In [1]: a = np.zeros((2,3,4,5,6))
In [2]: len(a) Out[2]: 2
In [8]: np.rollaxis(a,0,len(a.shape)).shape Out[8]: (3, 4, 5, 6, 2)
So it behaves just like insert. But "len(a.shape)" is rather cumbersome, especially if you haven't given a a name yet:
It's available as a.ndim
Ryan
On Tue, Sep 21, 2010 at 12:48 PM, Ken Basye kbasye1@jhu.edu wrote:
If that's going to break too much code, here's a pathway that might be acceptable: Add a new function moveaxis() which works the way rollaxis() does for positive arguments but in the new way for negative arguments. Eventually, rollaxis could be deprecated to keep things tidy. This has the added advantage of using a name that seems to fit what the function does better - 'rollaxis' suggests a behavior like the roll() function which affects other axes, which isn't what happens.
My 2 cents: +1 on a new function, but I'd change the behavior for positive arguments too.
Currently, the API is (AFAICT): You give the index of the axis you want to move, and you give the index of the axis that you want the first axis to be moved in front of. This is super confusing!
I propose that a much better API would be: You give the index of the axis you want to move, and you give the index you *want* that axis to have. So we'd have the invariant: b = np.moveaxis(a, i, j) assert a.shape[i] == b.shape[j] This is way easier to think about, at least for me. And it solves the problem with negative indices too.
BTW, note that that the documentation for rollaxis is actually self-contradictory at the moment: http://docs.scipy.org/doc/numpy/reference/generated/numpy.rollaxis.html At the top it seems to document the behavior that I propose ("Roll the specified axis backwards, until it lies *in a given* position."), and then in the details it describes the actual behavior("The axis is rolled until it lies *before* this position"). I take this as further evidence that the current behavior is unnatural and confusing :-).
-- Nathaniel