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 <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