Re: [Numpydiscussion] A proposed change to rollaxis() behavior for negative 'start' values
Adding to an old discussion thread (see below) ... an implementation of the proposed functionality: from numpy import rollaxis def moveaxis(a, i, j = 0): """ move axis i of array a to position j """ n = a.ndim i = i if i >= 0 else i + n if j > i: return rollaxis(a, i, j + 1) elif j >= 0: return rollaxis(a, i, j) elif j == 1: return rollaxis(a, i, n) elif j >= i: return rollaxis(a, i, j + 1) else: return rollaxis(a, i, j) Examples: In [464]: a = numpy.ones((3,4,5,6)) In [465]: moveaxis(a,2,0).shape Out[465]: (5, 3, 4, 6) In [466]: moveaxis(a,2,1).shape Out[466]: (3, 5, 4, 6) In [467]: moveaxis(a,2,2).shape Out[467]: (3, 4, 5, 6) In [468]: moveaxis(a,2,3).shape Out[468]: (3, 4, 6, 5) In [469]: moveaxis(a,2,4).shape  ValueError: rollaxis: start (5) must be >=0 and < 5 In [470]: moveaxis(a,2,1).shape Out[470]: (3, 4, 6, 5) In [471]: moveaxis(a,2,2).shape Out[471]: (3, 4, 5, 6) In [472]: moveaxis(a,2,3).shape Out[472]: (3, 5, 4, 6) In [473]: moveaxis(a,2,4).shape Out[473]: (5, 3, 4, 6) In [474]: moveaxis(a,2,5).shape  ValueError: rollaxis: start (1) must be >=0 and < 5 On Thu, Sep 23, 2010 at 11:33 AM, Nathaniel Smith wrote:
On Tue, Sep 21, 2010 at 12:48 PM, Ken Basye
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 selfcontradictory 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
Have you considered using .transpose(...) instead? In [4]: a = numpy.ones((3,4,5,6)) In [5]: a.transpose(2,0,1,3).shape Out[5]: (5, 3, 4, 6) In [6]: a.transpose(0,2,1,3).shape Out[6]: (3, 5, 4, 6) In [7]: a.transpose(0,1,2,3).shape Out[7]: (3, 4, 5, 6) In [8]: a.transpose(0,1,3,2).shape Out[8]: (3, 4, 6, 5)
On Sat, Feb 16, 2013 at 10:45 AM, Bradley M. Froehle
wrote:
Have you considered using .transpose(...) instead?
My apologies... I didn't read enough of the thread to see what the issue was about. I personally think rollaxis(...) is quite confusing and instead choose to use .transpose(...) for clarity. You can interpret my suggestion as a means of implementing moveaxis w/o calling rollaxis. In fact rollaxis is built out of the .transpose(...) primitive anyway. Cheers, Brad
participants (2)

Bradley M. Froehle

Thomas Coffee