TAGS :Viewed: 11 - Published at: a few seconds ago

[ Reverse certain rows in N by 2 array ]

I have an N by 2 array like this one:

[[9 1]
 [0 5]
 [6 3]
 [2 4]
 [3 5]
 [4 1]
 [2 7]
 [6 8]
 [7 9]
 [8 0]]

After I make a search in this matrix, I return some indices where the rows must be permuted.

In my case, I had w=[1 0 9 8 7].

I use this code to permute the 2 columns ONLY on selected rows.

        for x in w:
            self.nodes[x] = roll (self.nodes[x], 1)

The result is correct like this:

[[1 9]  *
 [5 0]  *
 [6 3]
 [2 4]
 [3 5]
 [4 1]
 [2 7]
 [8 6]  *
 [9 7]  *
 [0 8]] *

The starred rows were correctly permuted.

I want to know if there is a ONE-LINER numpy expression that does all this trick.

The important fact here is the speed of the operation.

Answer 1


This works by applying the roll to a copy of a only at indices w and then setting those in the original a with the rolled values:

a[w] = np.roll(a[w], 1, axis=1)

Someone had an answer (I think @seberg, but it's now deleted) that showed that for two columns rolling is equivalent to reversing, you do not actually need to roll, and can use the reversing by index trick as so:

a[w] = a[w, ::-1]

For large arrays, the timing is similar. For shorter arrays, the roll solution is slower. Here is the timing.

N = 10
a = np.arange(N*2).reshape(-1,2)
w = np.random.choice(np.arange(N), size=N/2, replace=False)

timeit a[w] = np.roll(a[w],1,1)
10000 loops, best of 3: 23.2 µs per loop

timeit a[w] = a[w, ::-1]
100000 loops, best of 3: 8.07 µs per loop

N = 1000
a = np.arange(N*2).reshape(-1,2)
w = np.random.choice(np.arange(N), size=N/2, replace=False)

timeit a[w] = np.roll(a[w],1,1)
10000 loops, best of 3: 113 µs per loop

timeit a[w] = a[w, ::-1]
10000 loops, best of 3: 93.6 µs per loop

N = 100000
a = np.arange(N*2).reshape(-1,2)
w = np.random.choice(np.arange(N), size=N/2, replace=False)

timeit a[w] = np.roll(a[w],1,1)
100 loops, best of 3: 10.8 ms per loop

timeit a[w] = a[w, ::-1]
100 loops, best of 3: 9.63 ms per loop

Answer 2


self.nodes[w] = np.asarray(map(lambda x: np.roll(x,1), self.nodes[w]))