bturnip
bturnip

Reputation: 95

Numpy: how to roll 1 "row" in an array of arrays

I'm creating an 2d numpy array, with a simplified example like something like this:

COL01 = np.array(["A", "D", "G"])
COL02 = np.array(["B", "E", "H"])
COL03 = np.array(["C", "F", "I"])

GRID = np.array([[COL01], [COL02], [COL03]])

I'm passing the GRID around in my code. I want to be able to modify GRID by rolling ONLY one of the arrays that makes up its component rows. For instance, I want to pass GRID into a function with a row number and number of positions to roll, and then return the result.

How can I roll the single row independently? I tried following the answer from here: [Roll rows of a matrix independently, but I couldn't figure out how to adapt that answer to my problem.

Upvotes: 8

Views: 4075

Answers (2)

Joe Kington
Joe Kington

Reputation: 284582

You can do this by selecting the row you want to operate on and using numpy.roll.

Let's say we want to roll the first row one place to the right:

import numpy as np

grid = np.array([['A', 'D', 'G'],
                 ['B', 'E', 'H'],
                 ['C', 'F', 'I']])

grid[0] = np.roll(grid[0], 1)
print grid

This yields:

[['G' 'A' 'D']
 ['B' 'E' 'H']
 ['C' 'F' 'I']]

Notice that we're modifying the original array.

You should decide whether you want to operate on the array in-place (modifying the original) or if you want to make a copy each time. Repeated calls will have different effects depending on what you decide:

import numpy as np

def independent_roll_inplace(arr, ind, amount):
    arr[ind] = np.roll(arr[ind], amount)

def independent_roll_copy(arr, ind, amount):
    arr = arr.copy()
    arr[ind] = np.roll(arr[ind], amount)
    return arr

grid = np.array([['A', 'D', 'G'],
                 ['B', 'E', 'H'],
                 ['C', 'F', 'I']])

As an example of the difference, if we make a copy each time, we start "fresh" with the original grid. Repeated calls have no effect on the original:

print 'Roll the second row one place'
print independent_roll_copy(grid, 1, 1)
print 'Roll the second row two places'
print independent_roll_copy(grid, 1, 2)
print 'Roll the second row three places'
print independent_roll_copy(grid, 1, 3)

This yields:

Roll the second row one place
[['A' 'D' 'G']
 ['H' 'B' 'E']
 ['C' 'F' 'I']]
Roll the second row two places
[['A' 'D' 'G']
 ['E' 'H' 'B']
 ['C' 'F' 'I']]
Roll the second row three places
[['A' 'D' 'G']
 ['B' 'E' 'H']
 ['C' 'F' 'I']]

However, if we're modifying the original each time, we'd get the same result by rolling one place multiple times:

for _ in range(3):
    print 'Roll the first row one place, modifying the original'
    independent_roll_inplace(grid, 0, 1)
    print grid

Yielding:

Roll the second row one place, modifying the original
[['A' 'D' 'G']
 ['H' 'B' 'E']
 ['C' 'F' 'I']]
Roll the second row one place, modifying the original
[['A' 'D' 'G']
 ['E' 'H' 'B']
 ['C' 'F' 'I']]
Roll the second row one place, modifying the original
[['A' 'D' 'G']
 ['B' 'E' 'H']
 ['C' 'F' 'I']]

Upvotes: 11

Abhishek Mittal
Abhishek Mittal

Reputation: 366

This code might solve your problem.

REV_GRID is the rolled over version of GRID.

COL01 = ["A", "D", "G"]
COL02 = ["B", "E", "H"]
COL03 = ["C", "F", "I"]

GRID = []
GRID.append(COL01)
GRID.append(COL02)
GRID.append(COL03)

REV_GRID = []

for col in GRID:
    REV_GRID.append(col[::-1])

print GRID
print REV_GRID

Please let me know if it does not solve your problem. We will work on that.

Upvotes: 0

Related Questions