Converting Between Matrix Subscripts and Linear Indices (Like Ind2Sub/Sub2Ind in Matlab)

Converting between matrix subscripts and linear indices (like ind2sub/sub2ind in matlab)

This is not something I've used before, but according to this handy dandy Matlab to R cheat sheet, you might try something like this, where m is the number of rows in the matrix, r and c are row and column numbers respectively, and ind the linear index:

MATLAB:

[r,c] = ind2sub(size(A), ind)

R:

r = ((ind-1) %% m) + 1
c = floor((ind-1) / m) + 1

MATLAB:

ind = sub2ind(size(A), r, c)

R:

ind = (c-1)*m + r

sub2ind all x and y coordinates of a matrix

If you want all of the elements of an array A as linear subscripts, this can be done simply via:

IND = 1:numel(A);

This works for any size or dimension array.

More on array indexing in Matlab, including the difference between linear indexing and logical indexing. When you use find you're essentially using logical indexing to obtain linear indexing. The find function can be used to reliably obtain all of your linear indices, via IND = find(A==A);, but this is horrendously inefficient.

Accessing values using subscripts without using sub2ind

This may be faster than using SUB2IND:

[r,c] = size(M);  % Get the size of M
vals = M(I+r.*(J-1)); % Compute a linear index with vector operations

How to get the linear index for a numpy array (sub2ind)

I think you want to use np.ravel_multi_index. With the zero based indexing of numpy, and taking into account that matlab arrays are Fortran style, the equivalent to your matlab example is:

>>> np.ravel_multi_index((1, 0, 1), dims=(3, 4, 2), order='F')
13

Just so you understand what is going on, you could get the same result with the dot product of your indices and the strides of the array:

>>> a = np.random.rand(3, 4, 2)
>>> np.dot((1, 0, 1), a.strides) / a.itemsize
9.0
>>> np.ravel_multi_index((1, 0, 1), dims=(3, 4, 2), order='C')
9
>>> a[1, 0, 1]
0.26735433071594039
>>> a.ravel()[9]
0.26735433071594039

Return subscripts of a variable dimension matrix

I assume by "the indices [x1 x2 ... xd]" you mean the subscripts along each dimension of the equivalent d-dimensional array.

You need to convert L and d to a dimension array, and then capture multiple argouts from ind2sub. Here's a function that does so. You can call it like x = myind2sub(L, d, i).

function out = myind2sub(L, d, ix)

sz = repmat(L, [1 d]); %// dimension array for a d-dimension array L long on each side
c = cell([1 d]); %// dynamically sized varargout
[c{:}] = ind2sub(sz, ix);
out = [c{:}];

But you should also ask why you're storing it in a linear array and calculating subscripts, instead of just storing it in a multidimensional array in the first place. In Matlab, a multidimensional array is stored in a contiguous block of memory, so it's efficient, and you can index in to it using either multidimensional subscripts or linear indexing. If you have a linear array, just call reshape(myarray, sz) to convert it to the multidimensional equivalent.

MATLAB ind2sub equivalent 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!

MATLAB sub2ind using vectors

Suppose you want to select A(1:2,2:3):

% Row and column indexes
rind = 1:2;
cind = 2:3;

pos = bsxfun(@plus,rind', size(A,2)*(cind-1));

pos =
6 11
7 12

You might want to reshape it into a column vector pos(:), or in one line with a call to reshape().

Create new matrix based on row and column subscripts

Yes, you can index 2D matrices with a single index value that is the concatenation of the columns -- like turning your matrix into a vector by column-by-column. For example, you could access A(4,2) simply using A(8).

So, all you need to do is create a new matrix of indices and then access A at those values:

% input data array
A = [10 11 12 13 14 15;
16 17 18 19 20 21;
22 23 24 25 26 27;
28 29 30 31 32 33];

% number of rows
N_rows = size(A,1);

% row indices
r = [1 1 1;
1 1 1;
3 3 3;
3 3 3;
4 4 4];

% column indices
c = [1 3 6;
1 2 4;
1 2 6;
1 4 5;
1 5 6];

% element indices
idx = (c - 1)*N_rows + r;

% new indexed array
B = A(idx);

% display outputs
disp(B)


Related Topics



Leave a reply



Submit