#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
не является обязательным на каждой итерации, он используется только для обновления визуальных элементов, чтобы вы могли видеть изменения напрямую.