2016-10-19 9 views
1

Я хочу сделать условное построение вертикальных линий, которые меняют цвет на основе значения целочисленного вектора. Эти значения являются целыми числами от 0 до 4.Matlab: Можно ли векторизовать условное построение в цикле?

В настоящее время я использую цикл, чтобы пройти через таблицы для построения линий. Это работает, но для БОЛЬШИХ объемов данных требуется время, и мне интересно, можно ли его векторизовать.

Прилагается усеченная версия скрипта для циклического прохождения через вектор данных (образец), который просто проходит через вектор и отображает вертикальную линию, основанную на значении целого числа.

Я также приложу простую переменную, созданную мной под названием «ОБРАЗЕЦ» ниже, чтобы вставить ее в рабочее пространство.

for i=1:size(sample,1) 
    if  sample(i)==1 
     line([i i] ,[0 10], 'Marker','.','LineStyle','-','Color','r'); 
    elseif sample(i)==2 
     line([i i] ,[0 10], 'Marker','.','LineStyle','-','Color','b'); 
    elseif sample(i)==3 
     line([i i] ,[0 10], 'Marker','.','LineStyle','-','Color',[1 .5 0]); 
    elseif sample(i)==4 
     line([i i] ,[0 10], 'Marker','.','LineStyle','-','Color','g'); 
    end 
end 

Variable:

sample=[[3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4;0;0;0;0]]; 

Но это возможно «Vectorize» черчения таким образом без того, чтобы сделать это итерационно в цикле, как я сделал?

Picture of Desired Output

ответ

2

Воспользуйтесь тем, что при построении линии, MATLAB будет пропускать пункты, стоимость которых NaN.

% Your vector 
sample=[3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;2;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;3;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4;0;0;0;0]; 

% Your colors 
colors = [ 
    1 0 0 
    0 0 1 
    1 .5 0 
    0 1 0]; 

for idx = 1:4 
    % Find the index of each of your integers 
    X = find(sample == (idx)); 

    % Force X to be a row vector 
    X = X(:)'; 

    % Stack two X's on top of one another with a third row filled 
    % with NaNs. Fill in your Y values in the same way while 
    % you're at it. 
    Y = [zeros(size(X)); 10 + zeros(size(X)); nan(size(X))]; 
    X = [X; X; nan(size(X))]; %#ok<AGROW> 

    % Matlab is column major. By using the colon here, you 
    % produce a vector that is [X1 X1 nan X2 X2 nan ... etc.] 
    X = X(:); 
    Y = Y(:); 

    % Draw the line 
    line(X, Y, 'Marker', '.', 'LineStyle', '-', 'Color', colors(idx, :)) 
end 

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

Изменение входа в:

sample = zeros(1, 1e6); 
for idx = 1:4 
    sample(randi(1e6, 1, 1000)) = idx; 
end 

и бенчмаркинг с timeit дает время 0.0065706 секунд на моей машине, в то время как OP кода тестов на 1.4861 секунд.

+0

Ничего себе! Это определенно более эффективно и в соответствии с тем, что я искал. Используя контрольный тест, который я использовал ранее, для его запуска потребовалось около 3 секунд. Используя те же данные с этим модом, это заняло 0,007036 секунд. Так ~ 400 раз быстрее. :) – pelt

1

Я бы изменить что-то вроде:

colors=[1 0 0, 
     0 1 0, 
     1 0.5 0, 
     0 0 1]; 

nnsamples=samples(samples~=0); 

for ii=1:size(nnsamples,1) 

     line([ii ii] ,[0 10], 'Marker','.','LineStyle','-','Color',colors(nnsamples(ii),:)); 

end 
+0

Спасибо, я добавлю эти изменения в мой текущий скрипт, поскольку это более компактная форма того, что я делаю. Но мне все еще интересно, можно ли вообще удалить цикл, чтобы повысить эффективность, с которой это обрабатывается? Например, тестируя его по значениям 170K, оба типа обрабатываются всего за 3 секунды. – pelt

+0

170 тысяч участков на 3 секунды? Это быстро @pelt –

+0

@pelt проверить, если он быстрее с моим редактированием. –

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