user2378404
user2378404

Reputation: 85

Indexing of 2D array in matlab

I have a 6X4 matrix M1 containing only zeros. I also have two 1D arrays Y1 and Y2 each with length 4.The two arrays contain the desired index values. Now, I want to set(convert to 1) the elements of matrix M1 such that M1(Y1:Y2) is equal to 1

for ex: Y1=[1 2 2 1] and Y2=[3 4 5 3]
then, M1 should be

 1 0 0 1
 1 1 1 1 
 1 1 1 1
 0 1 1 0
 0 0 1 0
 0 0 0 0

I can do this using for loop. But is there any optimised way to do it? (I intend to use much bigger matrices)

Upvotes: 5

Views: 283

Answers (2)

Pavan Yalamanchili
Pavan Yalamanchili

Reputation: 12099

There may be other techniques, but this uses element wise operations which are insanely parallel.

A very simple solution. Thanks @Shai

>> [rows, cols] = size(M);
>> Y1=[1 2 2 1]; Y2=[3 4 5 3]; 
>> M = bsxfun(@ge, (1:rows)', Y1) & bsxfun(@le, (1:rows)', Y2)
M =
     1     0     0     1
     1     1     1     1
     1     1     1     1
     0     1     1     0
     0     0     1     0
     0     0     0     0

Unnecessarily complicated code

[rows, cols] = size(M);
offsets = ((1 : cols) - 1) * rows
Y1 = offsets + Y1;
Y2 = offsets + Y2;

M = reshape(1:numel(M), rows, cols);
M = bsxfun(@ge, M, Y1) & bsxfun(@le, M, Y2);

Upvotes: 6

Shai
Shai

Reputation: 114786

use cumsum!

>> szM = size(M1);
>> M1( sub2ind( szM, Y1, 1:szM(2) ) ) = 1
M1 =
 1     0     0     1
 0     1     1     0
 0     0     0     0
 0     0     0     0
 0     0     0     0
 0     0     0     0
>> M1( sub2ind( szM, Y2+1, 1:szM(2) ) ) = -1
M1 =
 1     0     0     1
 0     1     1     0
 0     0     0     0
-1     0     0    -1
 0    -1     0     0
 0     0    -1     0
>> M = cumsum(M,1)
M =
 1     0     0     1
 1     1     1     1
 1     1     1     1
 0     1     1     0
 0     0     1     0
 0     0     0     0

A pitfall: If any of Y2 equals 6 than setting Y2+1 to -1 will exceed matrix dimension.
To fix this you can add two lines before setting to -1 the elements of M:

>> cols = 1:szM(2);
>> sel = Y2 < szM(1);
>> M1( sub2ind( szM, Y2(sel)+1, cols(sel) ) ) = -1

A spin-off for Pavan Yalamanchili's answer using bsxfun: (hover to see:)

using bsxfun without offsets:
M1 = bsxfun( @ge, (1:size(M1,1))', Y1 ) & bsxfun( @le, (1:size(M1,1))', Y2 );

Upvotes: 8

Related Questions