Matlab has two functions for converting matrix subscripts to linear indices and vice versa. (ind2sub and sub2ind)
I found the equivalent for R but is there an equivalent way in Python?
A Google search lead me to this link: https://github.com/jjakeman/pyheat/blob/master/utilities/math_utils.py
From what I can tell, there is no direct implementation of those functions in MATLAB.
Just turns out I can't read the documentation properly. If you want the functionality of sub2ind
, you'll want the ravel_multi_index
function. The function declaration says that you require two inputs. The first input is a 2D numpy
array where each row are the locations for a particular dimension. For example, if you wanted to apply ind2sub
on a 2D matrix, you would specify a 2D numpy
array where the first row consists of all of the row locations you want, and the second row consists of all of the column locations you want. The second input is tuple that determines the size of each dimension, so for a 2D array, it'd be the number of rows and columns.
To do ind2sub
, you'd want the unravel_index
function. The first input is an array of linear indices that you want converted into locations of each dimension in your array. The second input is a tuple of dimensions like previously.
I'm going to leave the post at the bottom for posterity, in case you want to try and implement these yourself.
However, you can certainly implement those yourself. I'm assuming that because you tagged your post with numpy
that you'll want a numpy
-esque solution. Remember, in numpy
you access elements in row major, not column major, and so given two arrays such that one is for row and the other for column indices (0-indexed), sub2ind
for 2D matrices is very simply:
def sub2ind(array_shape, rows, cols):
return rows*array_shape[1] + cols
array_shape
is an array of two elements where the first element is the number of rows in the matrix and the second element is the number of columns. If you recall, you can access an element in a row-major matrix by:
ind = r*cols + c
(r,c)
are the row and column index you want, provided it's 0-indexed. To go the opposite way, you would use integer division and the modulus:
def ind2sub(array_shape, ind):
rows = (ind.astype('int') / array_shape[1])
cols = (ind.astype('int') % array_shape[1]) # or numpy.mod(ind.astype('int'), array_shape[1])
return (rows, cols)
Here, the output is a two-element tuple where the first element is the row locations and the second element is the column locations. To summarize ind2sub
, to access the row you want, you take the linear index and do an integer division with the columns. To get the column you want, you find the modulus or the remainder. Going to 3 dimensions and onwards is a bit more complicated. I'll leave you to take a look at the link I referred above for more details.
Obviously, I didn't place any error checking in the above functions, so you'd obviously use array_shape
to your advantage in that case. A better way of doing what you want would be something like:
def sub2ind(array_shape, rows, cols):
ind = rows*array_shape[1] + cols
ind[ind < 0] = -1
ind[ind >= array_shape[0]*array_shape[1]] = -1
return ind
def ind2sub(array_shape, ind):
ind[ind < 0] = -1
ind[ind >= array_shape[0]*array_shape[1]] = -1
rows = (ind.astype('int') / array_shape[1])
cols = ind % array_shape[1]
return (rows, cols)
I did some basic error checking to ensure that no rows or columns for sub2ind
or linear indices for ind2sub
are out of bounds. I set those locations to -1 so you know you messed up somewhere.
Good luck!
I think you want ravel_multi_index and unravel_index
Building on @rayryeng and @theblackcat's answers, you should also note that you will have to use Fortran style indexing, and recall that Python is 0 indexed whilst MATLAB is 1 indexed.
The Fortran style requirement tricked me up for a bit.
In Python:
np.unravel_index(7, [1, 2, 3, 4], 'F')
(0, 1, 0, 1)
and in MATLAB/Octave
[a, b, c, d] = ind2sub([1, 2, 3, 4], 8)
a = 1
b = 2
c = 1
d = 2
For 2D matrices, you can use Python's built-in divmod
function (returns the quotient and remainder of division). To get subscripts (r,c)
of a nrows x ncols
matrix, use:
(r, c) = divmod(ind, ncols)
for row-major ordering
(c, r) = divmod(ind, nrows)
for column-major ordering
For example, a 3x6 matrix in row-major (C style) ordering:
0 1 2 3 4 5
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)
6 7 8 9 10 11
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5)
12 13 14 15 16 17
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)
(0, 0) = divmod(0, 6)
(0, 3) = divmod(3, 6)
(1, 0) = divmod(6, 6)
(1, 5) = divmod(11, 6)
(2, 2) = divmod(14, 6)
A 3x6 matrix in column-major (Fortran style) ordering:
0 3 6 9 12 15
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)
1 4 7 10 13 16
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5)
2 5 8 11 14 17
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)
(0, 0) = divmod(0, 3) #r=0, c=0
(1, 0) = divmod(3, 3) #r=0, c=1
(2, 0) = divmod(6, 3) #r=0, c=2
(3, 2) = divmod(11, 3) #r=2, c=3
(4, 2) = divmod(14, 3) #r=2, c=4
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With