2016-04-21 3 views
1

Предположим, что у нас есть три m-на-n матрицы равного размера: A, B, C.Векторизация кода MATLAB

Каждая колонка в C представляет временные ряды.
A - максимальный рабочий (по длине фиксированного окна) каждого временного ряда в C.
B - минимальный пробег (над фиксированной длиной окна) каждого временного ряда в C.

Есть ли способ определить T в векторном формате?

[nrows, ncols] = size(A); 
T = zeros(nrows, ncols); 
for row = 2:nrows       %loop over the rows (except row #1). 
    for col = 1:ncols      %loop over the columns. 
     if  C(row, col) > A(row-1, col) 
      T(row, col) = 1; 
     elseif C(row, col) < B(row-1, col) 
      T(row, col) = -1; 
     else 
      T(row, col) = T(row-1, col); 
     end 
    end 
end 

Это то, что я придумал до сих пор:

T = zeros(m, n); 
T(C > circshift(A,1)) = 1; 
T(C < circshift(B,1)) = -1; 
+0

Можете ли вы показать пример того, что 'T', как ожидается, будет? Найти это немного сложно, чтобы следовать коду ... Можете ли вы также представить пример матрицы ввода? – rayryeng

+0

@rayryeng Я редактировал вопрос и менял имена переменных индекса цикла от 'm' до' row' и от 'n' до' col'. Надеюсь, что это станет проще. Я все еще пытаюсь придумать хороший пример того, как должен выглядеть * T *. – bluebox

+0

Я сам выработаю код и посмотрю, смогу ли я это понять. – rayryeng

ответ

2

Ну, проблема была связана с частью ELSE условного оператора. Итак, после продолжительной ментальной тренировки, вот как я подвел итог, чтобы векторизовать hell-outta все.

Теперь этот подход основан на сопоставлении. Мы получаем столбец пробежки или острова 1s, соответствующие маске 2D для части ELSE и присваиваем им те же теги. Затем переходим к start-1 вдоль каждого столбца каждого такого запуска и сохраняем это значение. Наконец, индексирование в каждый такой start-1 с этими помеченными номерами, которые будут работать как индексы отображения, предоставит нам все элементы, которые должны быть установлены в новом выходе.

Вот реализация выполнить все эти стремления -

%// Store sizes 
[m1,n1] = size(A); 

%// Masks corresponding to three conditions 
mask1 = C(2:nrows,:) > A(1:nrows-1,:); 
mask2 = C(2:nrows,:) < B(1:nrows-1,:); 
mask3 = ~(mask1 | mask2); 

%// All but mask3 set values as output 
out = [zeros(1,n1) ; mask1 + (-1*(~mask1 & mask2))]; 

%// Proceed if any element in mask3 is set 
if any(mask3(:)) 

    %// Row vectors for appending onto matrices for matching up sizes 
    mask_appd = false(1,n1); 
    row_appd = zeros(1,n1); 

    %// Get 2D mapped indices 
    df = diff([mask_appd ; mask3],[],1)==1; 
    cdf = cumsum(df,1); 

    offset = cumsum([0 max(cdf(:,1:end-1),[],1)]); 
    map_idx = bsxfun(@plus,cdf,offset); 
    map_idx(map_idx==0) = 1; 

    %// Extract the values to be used for setting into new places 
    A1 = out([df ; false(1,n1)]); 

    %// Map with the indices obtained earlier and set at places from mask3 
    newval = [row_appd ; A1(map_idx)]; 
    mask3_appd = [mask_appd ; mask3]; 
    out(mask3_appd) = newval(mask3_appd); 

end 
+0

Дорогой Бог. Я не знаю, как, черт возьми, ты это понял. +1. – rayryeng

+0

@rayryeng Пара часов психических пыток точно;) – Divakar

+0

Святая корова, это невероятно !! +1 – bluebox

2

Выполнение этого векторизованную довольно трудно, потому что выход текущей строки зависит от вывода предыдущей строки. Выполнение векторизованных операций обычно означает, что каждый элемент должен выделяться самостоятельно, используя некоторые отношения, которые не зависят от других элементов, которые его окружают.

У меня нет данных о том, как вы достигнете этого без цикла for, но я могу помочь вам сократить ваши операции до одного вместо двух. Вы можете выполнить назначение векторизованным в строке, но я не вижу, как вы все это сделаете одним выстрелом.

Таким образом, попробовать что-то вроде этого, вместо:

[nrows, ncols] = size(A); 
T = zeros(nrows, ncols); 
for row = 2:nrows       
    out = T(row-1,:); %// Change - Make a copy of the previous row 
    out(C(row,:) > A(row-1,:)) = 1; %// Set those elements of C 
            %// in the current row that are larger 
            %// than the previous row of A to 1 
    out(C(row,:) < B(row-1,:)) = -1; %// Same logic but for B now and it's 
            %// less than and the value is -1 instead 
    T(row,:) = out; %// Assign to the output 
end 

Я в настоящее время выяснить, как сделать это с помощью каких-либо петель вообще. Я буду держать вас в курсе.

+0

Спасибо, это очень полезно! +1 – bluebox

Смежные вопросы