Построение графика с использованием цикла for в MATLAB

#matlab #graphing

#matlab #for-цикл #построение #График #matlab-рисунок

Вопрос:

Я пытаюсь построить простой график с использованием цикла for, как показано ниже

 x=linspace(0,2*pi,100);
for i=1:numel(x)
    y=sin(x(i));
    plot(x(i),y)
    hold on
end
  

Однако на моем рисунке ничего не отображается. Почему это так?

Комментарии:

1. Мне искренне интересно: откуда у вас возникла идея, что именно так вы должны подходить к проблеме? Этому учили в каком-то классе? Вы читали это в Интернете? Вы только что просмотрели документацию и попробовали что-то сделать?

2. ну, в настоящее время я кое-что делаю в MatConvNet и попросил построить график ошибок, который вычисляется в for цикле, скажем, для 2000 итераций. Вот почему я пытаюсь использовать приведенный выше код, потому что, когда я пытался построить график ошибок, он был пуст.

3. Ну, построение графика внутри цикла, как правило, плохая идея (с точки зрения производительности), поэтому старайтесь избегать этого, если нет абсолютно никакого другого пути. Лучший подход заключается в том, чтобы сначала вычислить все, что вы хотите отобразить, и вызвать только plot один раз после этого. Если вы знаете, сколько итераций у вас будет, должно быть просто выделить матрицу размера numDataPoints * numIterations , а затем просто сохранить ваши векторы ошибок на потом (то есть, если вы не предпочитаете хранить только одно значение, такое как SSE или RMSE, и в этом случае подойдет вектор нумерации размеров). Удачи!

Ответ №1:

Почему это происходит…

При plot(x(i),y) этом вы строите 100 отдельных точек (по одной на каждой итерации), и они не отображаются по умолчанию. Поэтому график выглядит пустым.


Решение 1: векторное вычисление и прямое построение

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

 x = linspace(0,2*pi,100);
y = sin(x);
plot(x,y);
  

Обратите внимание, что y это вектор, а также x и который y(n) равен sin(x(n)) для всех n . Если вы хотите построить сами точки, используйте LineSpec-синтаксис при вызове plot , подобном этому 1:

 plot(x,y,'*');
  

1) Возможны и другие типы точек, см. Связанную документацию выше.


Решение 2. вычислите значения в цикле for и постройте график после этого

Если вы хотите вычислить значения в цикле for и построить его после этого: предварительно выделите необходимую переменную (в данном случае y ), вычислите значения в цикле for и, наконец, постройте его с помощью одной единственной команды после вычисления.

 x = linspace(0,2*pi,100);

y = zeros(size(x));
for i = 1:numel(x)
    y(i) = sin(x(i));
end

plot(x,y);
  

Решение 3. Динамически обновлять график при вычислении

В случае, если вы настаиваете на построении графика в рамках каждой итерации, предыдущий код из решения 2 можно расширить следующим образом: создайте фигуру, добавьте к ней «пустой» график и сохраните его дескриптор. Внутри цикла for вычислите значения и добавьте их в y -vector, как показано выше. В качестве последнего шага вы можете обновить график, изменив его XData YData свойства and и вызвав drawnow . Обратите внимание, что вызов plot каждый раз в цикле for является излишне дорогостоящим, и я не рекомендую его.

 % create figure and plot
figure;
ph = plot(0,0);
ax = gca;
set(ax,'XLim',[0,2*pi]);
set(ax,'YLim',[-1,1]);

% calculate and update plot
x = linspace(0,2*pi,100);
y = zeros(size(x));
for i = 1:numel(x)
    y(i) = sin(x(i));
    set(ph,'XData',x(1:i));
    set(ph,'YData',y(1:i));
    drawnow;
end
  

Комментарии:

1. Спасибо за ответ, но я намерен использовать for цикл для построения графика. Значит ли это, что я не могу рисовать непрерывную линию с помощью for цикла?

2. Чего вы хотите достичь в итоге? Создание графика значений, вычисленных в цикле for? Или это действительно нужно рисовать на каждой итерации ? Если да, то почему?

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

4. @cathy305 Я обновил свой ответ, чтобы он охватывал все возможности.

Ответ №2:

Простой подход

Если вы хотите нарисовать кривую при добавлении данных, попробуйте выполнить следующее:

 x = linspace(0,2 * pi, 100);
y = zeros(size(x));
for i=1:numel(x)
     y(i) = sin(x(i));
     plot(x(1:i), y(1:i), 'color', 'r')
     drawnow();
end
  

Имейте в виду, что график автоматически пытается установить пределы x и y (кривая масштабируется до окна графика), чтобы предотвратить это, вам придется вручную устанавливать пределы x и y с xlim помощью and ylim .

Как написал Мэтт в своем ответе, вызов plot на каждой итерации является довольно дорогостоящим (т. Е. отнимает много времени). Поэтому я предлагаю использовать источники данных:

Обновление графика с использованием источников данных

 % Create a panel and axes object
h_panel = uipanel;
h_axes = axes( 'Parent', h_panel);

% Create data sources
x = linspace(0,2 * pi, 100);
y = zeros(size(x));

% Create graph object, in this case stairs 
% and bind the variables x and y as its data sources
h_stairs = stairs(h_axes, x, y, 'XDataSource', 'x', 'YDataSource', 'y');

for i=1:size(x)
    y(i) = sin(x(i));
    % Update the data of the stairs graph
    refreshdata(h_stairs); 
    drawnow();
end
  

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