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)
Two-dimensional (2D) arrays are indexed by two subscripts, one for the row and one for the column. Each element in the 2D array must by the same type, either a primitive type or object type.
Array indexingIndices are provided as (row, column). So the index (5, 6) selects the element on the fifth row and sixth column. An index like (5, 6) selects a single element of an array, but we can also access sections of the matrix, or slices.
In most programming languages, the first element of an array is element 0. In MATLAB, indexes start at 1.
Indexing into a matrix is a means of selecting a subset of elements from the matrix. MATLAB® has several indexing styles that are not only powerful and flexible, but also readable and expressive. Indexing is a key to the effectiveness of MATLAB at capturing matrix-oriented ideas in understandable computer programs.
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
withoutoffsets
:M1 = bsxfun( @ge, (1:size(M1,1))', Y1 ) & bsxfun( @le, (1:size(M1,1))', Y2 );
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);
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