Roll rows of a matrix independently
Sure you can do it using advanced indexing, whether it is the fastest way probably depends on your array size (if your rows are large it may not be):
rows, column_indices = np.ogrid[:A.shape[0], :A.shape[1]]
# Use always a negative shift, so that column_indices are valid.
# (could also use module operation)
r[r < 0] += A.shape[1]
column_indices = column_indices - r[:, np.newaxis]
result = A[rows, column_indices]
Shift rows of a numpy array independently
Inspired by Roll rows of a matrix independently's solution, here's a vectorized one based on np.lib.stride_tricks.as_strided
-
from skimage.util.shape import view_as_windows as viewW
def strided_indexing_roll(a, r):
# Concatenate with sliced to cover all rolls
p = np.full((a.shape[0],a.shape[1]-1),np.nan)
a_ext = np.concatenate((p,a,p),axis=1)
# Get sliding windows; use advanced-indexing to select appropriate ones
n = a.shape[1]
return viewW(a_ext,(1,n))[np.arange(len(r)), -r + (n-1),0]
Sample run -
In [76]: a
Out[76]:
array([[4, 0, 0],
[1, 2, 3],
[0, 0, 5]])
In [77]: r
Out[77]: array([ 2, 0, -1])
In [78]: strided_indexing_roll(a, r)
Out[78]:
array([[nan, nan, 4.],
[ 1., 2., 3.],
[ 0., 5., nan]])
Numpy: how to roll 1 row in an array of arrays
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']]
numpy.roll horizontally on a 2D ndarray with different values
By specifying a tuple in np.roll
you can roll an array along various axes. For example, np.roll(a, (3,2), axis=(0,1))
will shift each element of a
by 3 places along axis 0, and it will also shift each element by 2 places along axis 1. np.roll
does not have an option to roll each row by a different amount. You can do it though for example as follows:
import numpy as np
a = np.array([
[6, 3, 9, 2, 3],
[1, 7, 8, 1, 2],
[5, 4, 2, 2, 4],
[3, 9, 7, 6, 5],
])
shifts = np.c_[[1,2,1,3]]
a[np.c_[:a.shape[0]], (np.r_[:a.shape[1]] - shifts) % a.shape[1]]
It gives:
array([[3, 6, 3, 9, 2],
[1, 2, 1, 7, 8],
[4, 5, 4, 2, 2],
[7, 6, 5, 3, 9]])
python: shift each matrix inside a tensor independantly
Approach #1
Adapting strided-based
solution from the same linked Q&A for performance -
from skimage.util.shape import view_as_windows
def roll_along_second_axis_3dar(a, r):
r = np.asarray(r)
a_ext = np.concatenate((a,a[:,:-1,:]),axis=1)
n = a.shape[1]
idx = (n-r)%n
w = view_as_windows(a_ext,(1,n,1))[...,0,:,0]
return w[np.arange(len(idx)),idx].swapaxes(1,2)
Sample run -
In [11]: a
Out[11]:
array([[[44, 47, 64],
[67, 67, 9],
[83, 21, 36],
[87, 70, 88]],
[[88, 12, 58],
[65, 39, 87],
[46, 88, 81],
[37, 25, 77]]])
In [12]: roll_along_second_axis_3dar(a, r=[-1,1])
Out[12]:
array([[[67, 67, 9],
[83, 21, 36],
[87, 70, 88],
[44, 47, 64]],
[[37, 25, 77],
[88, 12, 58],
[65, 39, 87],
[46, 88, 81]]])
Approach #2
Going with your try, seems you were close enough. We could get to the final output with few modifications/corrections -
d1, d2, d3 = np.ogrid[:AB.shape[0], :AB.shape[1], :AB.shape[2]]
r[r < 0] += AB.shape[1]
D2 = ((d2 - r).transpose(2,1,0))%AB.shape[1]
out = AB[d1,D2,d3]
Numpy - multiple numpy.roll of 1D input array
Approach #1 : For elegance
Here's one way with broadcasting
-
In [44]: a
Out[44]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [45]: rolls
Out[45]: array([-1, 0, 1, 2])
In [46]: a[(np.arange(len(a))[:,None]-rolls) % len(a)]
Out[46]:
array([[1, 0, 9, 8],
[2, 1, 0, 9],
[3, 2, 1, 0],
[4, 3, 2, 1],
[5, 4, 3, 2],
[6, 5, 4, 3],
[7, 6, 5, 4],
[8, 7, 6, 5],
[9, 8, 7, 6],
[0, 9, 8, 7]])
Approach #2 : For memory/perf-efficiency
Idea mostly borrowed from - this post
.
We can leverage np.lib.stride_tricks.as_strided
based scikit-image's view_as_windows
to get sliding windows. More info on use of as_strided
based view_as_windows
.
from skimage.util.shape import view_as_windows
def multiroll_stridedview(a, r):
r = np.asarray(r)
# Concatenate with sliced to cover all rolls
a_ext = np.concatenate((a,a[:-1]))
# Get sliding windows; use advanced-indexing to select appropriate ones
n = len(a)
return view_as_windows(a_ext,n)[:,(n-r)%n]
Related Topics
What Are the Most Common Python Docstring Formats
What Does -1 Mean in Numpy Reshape
Combining Two Sorted Lists in Python
Modifying a List Inside a Function
Running Selenium with Headless Chrome Webdriver
Python: JSON.Loads Returns Items Prefixing with 'U'
Ignore Python Multiple Return Value
Replacing Column Values in a Pandas Dataframe
Django Passing Custom Form Parameters to Formset
How to Uninstall Anaconda Completely from MACos
How to Get a Random Number Between a Float Range
How to Check If Type of a Variable Is String
Selecting a Row of Pandas Series/Dataframe by Integer Index
Extract Images from PDF Without Resampling, in Python
Reading from a Frequently Updated File
Python' Is Not Recognized as an Internal or External Command
Get the Key Corresponding to the Minimum Value Within a Dictionary