Framester
Framester

Reputation: 35451

How to invert numpy.roll?

I have a for-loop that repeatedly calls roll and I want to invert the order of the created arrays.

I think I have overlooked some trivial way to do it, but so far I only have found 10000 3 5 ways not to do it.

In [1]: from numpy import roll  
In [2]: c = range(5)

## The code I want to invert
In [3]: for i in range(len(c)):
   ...:         c = roll(c, 1)
   ...:         print c
[4 0 1 2 3]
[3 4 0 1 2]
[2 3 4 0 1]
[1 2 3 4 0]
[0 1 2 3 4]    

## The result I want
[0 1 2 3 4]
[1 2 3 4 0]
[2 3 4 0 1]
[3 4 0 1 2]    
[4 0 1 2 3]    


## What I've tried:
In [4]: for i in range(len(c)):
   ...:         c = roll(c, -1)
   ...:         print c
[1 2 3 4 0]
[2 3 4 0 1] # <- false
[3 4 0 1 2]
[4 0 1 2 3]
[0 1 2 3 4]    
In [5]: for i in reversed(range(len(c))):
   ...:         c = roll(c, -i)
   ...:         print c
[4 0 1 2 3] # <- false
[2 3 4 0 1]
[4 0 1 2 3]
[0 1 2 3 4]
[0 1 2 3 4]    

In [6]: for i in reversed(range(len(c))):
        c = roll(c, i)
        print c
   ...:     
[1 2 3 4 0]
[3 4 0 1 2] # <- false
[1 2 3 4 0]
[0 1 2 3 4]
[0 1 2 3 4]

In [7]: for i in range(len(c)):
   ...:    c = roll(c, i)
   ...:    print c
   ...:     
[0 1 2 3 4]
[4 0 1 2 3] # <- false
[2 3 4 0 1]
[4 0 1 2 3]
[0 1 2 3 4]

In [8]: for i in range(len(c)):
   ...:         c = roll(c, -i)
   ...:         print c
   ...:     
[0 1 2 3 4]
[1 2 3 4 0]
[3 4 0 1 2] # <- false
[1 2 3 4 0]
[0 1 2 3 4]

Upvotes: 3

Views: 535

Answers (2)

denis
denis

Reputation: 21947

Fwiw, a different question: to invert np.rollaxis, I've found only this, using transpose:

import numpy as np

a = np.ones((3,4,5,6))
print a.shape

for ax in range( a.ndim ):
    print "ax %d:" % ax ,
    jtrans = np.arange( a.ndim )
    jtrans[0], jtrans[ax] = jtrans[ax], jtrans[0]
    b = a.transpose( jtrans )
    print b.shape, jtrans ,
    a = b.transpose( jtrans )  # and back
    print a.shape

# (3, 4, 5, 6)
# ax 0: (3, 4, 5, 6) [0 1 2 3] (3, 4, 5, 6)
# ax 1: (4, 3, 5, 6) [1 0 2 3] (3, 4, 5, 6)
# ax 2: (5, 4, 3, 6) [2 1 0 3] (3, 4, 5, 6)
# ax 3: (6, 4, 5, 3) [3 1 2 0] (3, 4, 5, 6)

Upvotes: 0

danodonovan
danodonovan

Reputation: 20341

How about

for i in range(len(c)):
    print c
    c = roll(c, len(c) - 1)

[0 1 2 3 4]
[1 2 3 4 0]
[2 3 4 0 1]
[3 4 0 1 2]
[4 0 1 2 3]

rolling everything all the way round (but one) and also printing before the first roll (so you get c as range(5) for the first line).

Or even your first solution, if you print c first

for i in range(len(c)):
    print c
    c = roll(c, -1)

[0 1 2 3 4]
[1 2 3 4 0]
[2 3 4 0 1]
[3 4 0 1 2]
[4 0 1 2 3]

Upvotes: 3

Related Questions