MATLAB ind2sub equivalent in Python

Matlab has two functions for converting matrix indexes into linear indexes and vice versa. (ind2sub and sub2ind)

I found an equivalent for R, but is there an equivalent way in Python?

+6
source share
3 answers

A google search leads me to this link: https://github.com/jjakeman/pyheat/blob/master/utilities/math_utils.py

From what I can say, there is no direct implementation of these functions in MATLAB .


As it turned out, I can’t read the documentation correctly. If you need sub2ind functionality, you will need the ravel_multi_index function. The function declaration says you need two inputs. The first input is a 2D numpy array, where each row is a location for a specific dimension. For example, if you want to use ind2sub in a 2D matrix, you must specify a 2D numpy array where the first row consists of all the desired row locations and the second row consists of all the column locations you want. The second input is a tuple that determines the size of each dimension, so for a 2D array this will be the number of rows and columns.

To make ind2sub , you will need the unravel_index function. The first entry is an array of linear indexes that you want to convert to the locations of each dimension in your array. The second entrance is a set of sizes as previously.

I am going to leave a message below for posterity if you want to try to implement them yourself.


However, you can, of course, implement them yourself. I assume that since you have noted the numpy message that you will need a numpy solution. Remember that in numpy you access the elements in the major row , not the major column , and therefore two arrays are specified, such as one for the row and the other for the column indices (0-index), sub2ind for 2D matrices is very simple:

 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 remember, you can access the item in the main line:

 ind = r*cols + c 

(r,c) - the index of the row and column you need, if it is 0-indexed. To go the opposite way, you have to use integer division and module:

 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 in which the first element is the location of the rows, and the second element is the location of the columns. To sum ind2sub to access the desired row, you take a linear index and do integer division with columns. To get the column you need, you will find a module or remainder. Going to 3 dimensions and on is a bit more complicated. I will leave you a look at the link above for more details.

Obviously, I did not post any errors in the above functions, so you would obviously use array_shape to your advantage in this case. The best way to do what you want would be something like this:

 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 indexes for ind2sub are limits. I set these places to -1 so that you know that you ruined something.

Good luck

+14
source

I think you want ravel_multi_index and unravel_index

+7
source

Based on the answers of @rayryeng and @theblackcat, you should also notice that you will need to use Fortran style indexing and remember that Python is indexed 0 and MATLAB is indexed by index.

The requirement of the Fortran style deceived me a little.

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 
+3
source

Source: https://habr.com/ru/post/983672/


All Articles