Related
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?
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
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.
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?
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
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.
I am trying to use a plotyy and hold on to plot four diagrams in two y axes and it did not work.
Can anybody see where is the problem?
It only plots the first two diagrams:
load dexpan2Cp;
x1=dexpan2Cp(:,2);
x1=x1/3600;
y1=((dexpan2Cp(:,3)+dexpan2Cp(:,4))/2000)*32.5;
load Dexpan2_2C;
x2=Dexpan2_2C(:,1);
x2=x2/3600;
y2=Dexpan2_2C(:,2);
A = importdata('Scan Session94-Dexpan19.txt','\t',5);
Dexpan19p=A.data;
save('Dexpan19p.mat','Dexpan19p');
x3=Dexpan19p(:,2);
x3=x3/3600;
y3=((Dexpan19p(:,3)+Dexpan19p(:,4))/2000)*32.5;
load Dexpan19C;
x4=Dexpan19C(:,1);
x4=x4/3600;
y4=Dexpan19C(:,2)+3.3;
x1 = x1(x1<115.7); y1 = y1(1: length(x1) , :);
x2 = x2(x2<115.7); y2 = y2(1: length(x2), :);
x3 = x3(x3<115.7); y3 = y3(1: length(x3), :);
x4 = x4(x4<115.7); y4 = y4(1: length(x4), :);
hold off;
figure;
[ax, h1, h2] = plotyy(x1,y1,x2,y2);
set(h1,'g',y1,'DisplayName','1');
set(h2,'b',y2,'DisplayName','2e');
hold(ax(1),'on');
plot(ax(1),x3,y3,'r',y3,'DisplayName','3');
hold(ax(2),'on');
plot(ax(2),x4,y4,'k',y4,'DisplayName','4');
xlabel('Time (h)');
ylabel(ax(1),' Pressure (MPa)');
ylabel(ax(2),'Tempereture (°C)');
legend('show');
You seem to be using invalid syntax, and not telling us what errors you are receiving when executing your code. In particular, your code errors out after plotting the first two lines -- hence why you are only getting 2 lines plotted.
To make it work, four of your lines should be changed to,
set(h1,'Color','g','DisplayName','1');
set(h2,'Color','b','DisplayName','2e');
plot(ax(1),x3,y3,'Color','r','DisplayName','3');
plot(ax(2),x4,y4,'Color','k','DisplayName','4');
I have to plot 1 line plot and 3 grouped scatter plots in a single plot window.
The following is the code I tried,
figure;
t1=0:0.1:10;
X = 2*sin(t1);
ts = 0:1:10;
Y1 = randi([0 1],length(ts),1);
Y2 = randi([0 1],length(ts),1);
Y3 = randi([0 1],length(ts),1);
plotyy(t1,X,[ts',ts',ts'],[Y1,Y2,Y3],'plot','scatter');
%plotyy(t1,X,[ts',ts',ts'],[Y1,Y2,Y3],'plot','plot');
The following are my questions,
The above code works if I replace 'scatter' by 'plot' (see commented out line), but 'scatter' works only for 1 data set and not for 3. Why?
How to individually assign colors to the 3 grouped scatter plots or plots?
Read the error message you're given:
Error using scatter (line 44) X and Y must be vectors of the same
length.
If you look at the documentation for scatter you'll see that the inputs must be vectors and you're attempting to pass arrays.
One option is to stack the vectors:
plotyy(t1,X,[ts';ts';ts'],[Y1;Y2;Y3],'plot','scatter');
But I don't know if this is what you're looking for, it certainly doesn't look like the commented line. You'll have to clarify what you want the final plot to look like.
As for the second question, I would honestly recommend not using plotyy. I may be biased but I've found it far to finicky for my tastes. The method I like to use is to stack multiple axes and plot to each one. This gives me full control over all of my graphics objects and plots.
For example:
t1=0:0.1:10;
X = 2*sin(t1);
ts = 0:1:10;
Y1 = randi([0 1],length(ts),1);
Y2 = randi([0 1],length(ts),1);
Y3 = randi([0 1],length(ts),1);
% Create axes & store handles
h.myfig = figure;
h.ax1 = axes('Parent', h.myfig, 'Box', 'off');
h.ax2 = axes('Parent', h.myfig, 'Position', h.ax1.Position, 'Color', 'none', 'YAxisLocation', 'Right');
% Preserve axes formatting
hold(h.ax1, 'on');
hold(h.ax2, 'on');
% Plot data
h.plot(1) = plot(h.ax1, t1, X);
h.scatter(1) = scatter(h.ax2, ts', Y1);
h.scatter(2) = scatter(h.ax2, ts', Y2);
h.scatter(3) = scatter(h.ax2, ts', Y3);
Gives you:
And now you have full control over all of the axes and line properties. Note that this assumes you have R2014b or newer in order to use the dot notation for accessing the Position property of h.ax1. If you are running an older version you can use get(h.ax1, 'Position') instead.
I have two vectors, c and d, whose histogram I need to plot side by side in the same figure in matlab. when i do
hist(c);
hold on;
hist(d)
the scale changes and I cant see the histogram of c vector. Where am i going wrong? Any help will be appreciated.
If you want the two to be in the same figure, you could try adjusting the X and Y limits to suit your needs (try help xlim and help ylim). However plotting them in the same figure might not always suit your needs, as a particular plot has to of course maintain a certain limit for X and Y.
If displaying them side by side in different figures would suffice however, you could consider using subplot():
>> A=[1 1 1 2 2];
>> B=[1 2 2 2 2];
>> figure(1);
>> hold on;
>> subplot(1,2,1);
>> hist(A);
>> subplot(1,2,2);
>> hist(B);
Resultant figure:
Notice how the different axis limits are maintained.
You can use axis([xmin xmax ymin ymax]) to control the x and y axis and select a range that will display both histograms. Depending on what you want your plot to look like, you may also want to try using nelements = hist(___) to get the number of elements in each bin and then plot them using bar(x,nelements) to control the location of each bar.
hist assumes you want to divide the range into 10 equal sized bins by default. If you want to use the same bins for both histograms, first find the range of your values and make a set of bin centers (e.g. binCenters = linspace(min(x), max(x), 15)'), then callhist(x, binCenters)`.
I use MATLAB histograms quite frequently and have wrote this small matlab script to plot two histograms (first one red and second blue) in one figure. The script is quite simple but the important thing is that the histograms should be comparable (i.e. equally spaced frequency bins).
function myhist(varargin)
% myhist function to plot the histograms of x1 and x2 in a single figure.
% This function uses the same xvalue range and same bins to plot the
% histograms, which makes comparison possible.
if nargin<2
x1 = cell2mat(varargin(1));
x2 = x1;
res = 100;
elseif nargin==2
x1 = cell2mat(varargin(1));
if length(cell2mat(varargin(2)))==1
res = cell2mat(varargin(2));
x2 = x1;
else
x2 = cell2mat(varargin(2));
res = 100;
end
elseif nargin>2
x1 = cell2mat(varargin(1));
x2 = cell2mat(varargin(2));
res = cell2mat(varargin(3));
end
if numel(x1)~=length(x1) || numel(x2)~=length(x2)
error('Inputs must be vectors.')
return
end
xrangel = max(min(x1),min(x2));
xrangeh = min(max(x1),max(x2));
x1_tmp = x1(x1>=xrangel & x1<=xrangeh);
x2_tmp = x2(x2>=xrangel & x2<=xrangeh);
xbins = xrangel:(xrangeh - xrangel)/res:xrangeh;
hist(x1_tmp,xbins)
hold on
h = findobj(gca,'Type','patch');
set(h,'FaceColor','r','EdgeColor','w');
hist(x2_tmp,xbins)