3

I'm trying to plot a simple graph using for loop as shown below

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

However, nothing appear on my figure. Why is that?

3
  • I'm genuinely interested: where did you get the idea that this is how you should approach the problem? Was it taught in some class? Did you read it online? Did you just go through the documentation and try things? Commented May 31, 2016 at 8:31
  • well, I'm currently doing some stuff on MatConvNet and asked to plot the error graph which is calculated within a for loop for, let say 2000 iterations. That is why I'm trying the above code cos when I tried to plot the error graph, it's empty. Commented May 31, 2016 at 8:39
  • Well, plotting inside a loop is generally a bad idea (in terms of performance) so try to avoid it unless there's absolutely no other way. The better approach is to first compute whatever it is you want plotted, and only call plot once afterwards. If you know how many iterations you are going to have, it should be straightforward to allocate a matrix of size numDataPoints * numIterationsand then just store your error vectors for later (that is unless you prefer to store just one value such as SSE or RMSE, in which case a vector of size numIterations would do). Good luck! Commented May 31, 2016 at 8:46

2 Answers 2

4

Why this happens...

With plot(x(i),y) you are plotting 100 single points (one in each iteration) and they are not shown by default. Therefore the plot looks empty.


Solution 1: Vectorized calculation and direct plot

I assume you meant to draw a continuous line. In that case no for-loop is needed because you can calculate and plot vectors directly in MATLAB. So the following code does probably what you want:

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

Note that y is a vector as well as x and that y(n) equals to sin(x(n)) for all n. If you want to plot the points itself, use LineSpec-syntax when calling plot like this1:

plot(x,y,'*');

1) Other types of points are possible as well, see the above linked documentation.


Solution 2: Calculate values within for-loop and plot afterwards

If you want to calculate the values within a for-loop and plot it afterwards: Pre-allocate the needed variable (in this case y), calculate the values within the for-loop and finally plot it with one single command after the calculation.

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

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

plot(x,y);

Solution 3: Dynamically update plot while calculating

In case you insist on plotting within each iteration, the previous code from Solution 2 can be expanded as follows: Create a figure, add an 'empty' plot to it and store its handle. Within the for-loop calculate the values and add them to the y-vector as shown above. As a last step you can update the plot by changing its XData and YData properties and calling drawnow. Note that calling plot every time within the for-loop is unnecessarily expensive and I don't recommend it.

% 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
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for the answer, but my intention is to use for loop to plot a graph. So does that mean I cannot draw continuous line using for loop?
What do you want to achieve in the end? Creating a plot of values calculated within a for-loop? Or does it really need to draw in each iteration? If yes, why?
Yes, I want to plot values, error values to be exact, calculated within a for-loop in each iteration to show that the error is actually decreasing as epoch increases, which means accuracy is getting higher.
@cathy305 I updated my answer so it should cover all the possibilities.
2

Simple approach

If you want to draw a curve as you add data, try the following:

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

Be aware that the plot automatically tries to set x and y limits (curve is scaled to the plot window), to prevent that you have to manually set the x- and y-limits with xlimand ylim.

As Matt wrote in his answer, calling plot in each iteration is quite expensive (i.e. time consuming). Therefore I suggest using datasources:

Update graph using data sources

% 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

The call to drawnow isn't neccessary in each iteration, it is only used to update the visuals, so you can see the changes directly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.