Индексирование 2D-массива в Matlab

У меня есть матрица размером 6х4 M1, содержащая только нули. У меня также есть два одномерных массива Y1 и Y2, каждый длиной 4. Два массива содержат желаемые значения индекса. Теперь я хочу установить (преобразовать в 1) элементы матрицы M1 так, чтобы M1(Y1:Y2) было равно 1

например: Y1=[1 2 2 1] и Y2=[3 4 5 3]
тогда M1 должен быть

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

Я могу сделать это с помощью цикла for. Но есть ли какой-нибудь оптимизированный способ сделать это? (Я собираюсь использовать матрицы гораздо большего размера)


person user2378404    schedule 19.06.2013    source источник


Ответы (2)


Могут быть и другие методы, но при этом используются безумно параллельные поэлементные операции.

Очень простое решение. Спасибо, @ Шай

>> [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

Излишне сложный код

[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);
person Pavan Yalamanchili    schedule 19.06.2013
comment
отличное использование bsxfun - но вы можете сделать это без использования offsets - person Shai; 19.06.2013
comment
@shai Ошибка все еще есть, исправляю. - person Pavan Yalamanchili; 19.06.2013
comment
ответ на мой вопрос можно найти, если навести курсор мыши на нижнюю часть моего ответа ;-) - person Shai; 19.06.2013
comment
но почему offset и весь бардак? bsxfun может сделать это однострочным! - person Shai; 19.06.2013
comment
@shai Это было первое, что пришло мне в голову. Я вижу, что есть более чистый способ сделать что-то :) Я тоже добавлю это решение. - person Pavan Yalamanchili; 19.06.2013
comment
ты получил мой +1 за ВЕСЕЛЬЕ с bsxfun;) - person Shai; 19.06.2013

используйте 1_!

>> 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

Ошибка: если любое из Y2 равно 6, чем установка Y2+1 на -1 будет превышать размер матрицы.
Чтобы исправить это, вы можете добавить две строки перед установкой на -1 элементов M:

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

Дополнительный результат для ответа Павана Яламанчили с использованием bsxfun: (наведите указатель мыши, чтобы увидеть :)

с использованием bsxfun без offsets:
M1 = bsxfun( @ge, (1:size(M1,1))', Y1 ) & bsxfun( @le, (1:size(M1,1))', Y2 );

person Shai    schedule 19.06.2013