MATLAB: plotting subplots in for loop - matlab

I'm trying to plot several subplots in a single figure.
The total number of subplots is dependent on the maximal value in a matrix: maximal value of 'i'.
I'd like to plot two variables in two subplots below each other for every value of i :slagtijd_start & slagfrequentie_start
So when the maximum value of i = 3, we have a subplot matrix of 2x3 axes,
if i = 4 --> 2x4 axes etc.
Plotting on the right postions works, except that matlab erases the previous subplots (previous values of i). In this case i = 3 and the figure only displays the two latest subplots. I've tried different things with 'hold on' etc. But I can't figure it out. It's probably a simple trick.
I've posted my code and resulting figure below,
Thanks in advance,
Mochje
figure(6)
hold on
for i = 1:max(piektijden_start(:,2))
startnummer = find(piektijden_start(:,2) == i);
slagtijd_start= diff(piektijden_start(startnummer));
slagfrequentie_start= (60./slagtijd_start);
subplot(2,i,i),plot(piektijden_start(startnummer(1:end-1),1),slagtijd_start)
hold on
xlabel('Tijd [s]')
ylabel('Slagtijd [s]')
title('Slagtijd')
subplot(2,i,i+i),plot(piektijden_start(startnummer(1:end-1),1),slagfrequentie_start)
hold on
plot(piektijden_start(startnummer(1:end-1),1),slagfrequentie_start,'.r')
xlabel('Tijd [s]')
ylabel('Slagfrequentie [N/min]')
title('Slagfrequentie')
end

Use something like
figure(6)
hold on
max_i = max(piektijden_start(:,2));
for i = 1:max_i
%// ...
subplot(2, max_i, i)
%// ...
subplot(2, max_i, i+max_i)
%// ...
end
The second argument to subplot is the number of subplot columns. The third is the addressed subplot, such that such that the first subplot is the first column of the first row, the second subplot is the second column of the first row, and so on

Related

Matlab - plotting function with a for loop over a matrix

I have an assignment which sounds like:
"“Grades per assignment”: A plot with the assignments on the x-axis and the grades on the y-axis. The x-axis must show all assignments from 1 to M, and the y-axis must show all grade −3 to 12. The plot must contain:
Each of the given grades marked by a dot. You must add a small random number (between -0.1 and 0.1) to the x- and y-coordinates of each dot, to be able tell apart the different dots which otherwise would be on top of each other when more than one student has received the same grade in the same assignment.
The average grade of each of the assignments plotted as a line"
For now i have created this function:
function gradesPlot(grades)
figure(2);
n_assignments=size(grades,2);
hold on; % Retain current plot when adding new plots.
for i = 1:n_assignments % Loop through every assignment.
% Scatter plot of assignment vs grades for that assignment.
% One assignment on every iteration.
n_assignments2=([1:size(grades,2)]);
scatter(n_assignments2,grades(:,i)'jitter', 'on', 'jitterAmount', 0.1)
hold off; % Set the hold state to off.
end
%Titles to the plot
title('Grades per assignment');
xlabel('Assignment');
ylabel('Given grades');
break;
end
when i run the code it says that the vectors must be same length.
And it looks like it doesn't loop over the matrix more than ones.
The test grades i am using as input is looking like this:
grades=[[-3,4,10];[7,4,12];[7,10,12];[0,4,4];[2,2,2];[2,2,2]]
I hope some of you guys can help me get this function to work - maybe in an easier way?
Thank you in advance
You should not turn off hold since it is tells MatLab to plot everything in the current active plot, roughly speaking. You can find a possible solution to your problem down below: I added some explanations in comments.
function gradesPlot(grades)
figure(2);
% Extract the relevant information: number of assignements, number of grades
[n_assignments,n_grades] = size(grades);
hold on; % Retain current plot when adding new plots.
for i = 1:n_assignments % Loop through every assignment.
% Scatter plot of assignment vs grades for that assignment.
% One assignment on every iteration
% For Scatter, you have to provide 2 vectors of the same size: in this
% way, we are putting al the dots corresponding to the grades of the
% i-th assignement in correspondence of the i-th coordinate on the x
% axis. We are also temporary saving in h the handle to the attributes
% of the dots, in order to retrieve the color.
h = scatter(i*ones(n_grades,1),grades(i,:),'jitter', 'on', 'jitterAmount', 0.1);
% This plots the horizontal line corresponding to the average of the
% grades related to the i-th assignement
l = line([i-0.5 i+0.5],[1,1]*mean(grades(i,2:end)));
% For using the same color as the dots.
l.Color = h.CData;
end
%Titles to the plot
title('Grades per assignment');
xlabel('Assignment');
ylabel('Given grades');
axis([0 n_assignments+1 -4 13])
end
Remember that the break command must be used inside a loop, not for exiting a function. Use return if you desire.

Highlight specific section of graph in MATLAB

I wish to highlight/mark some parts of a array via plot in MATLAB. After some research (like here) I tried to hold the first plot, find the indexes for highlighting and then a new plot, only with those points. However, those points are being drawn but all shifted to the beginning of the axis:
I'm currently trying using this code:
load consumer; % the main array to plot (157628x10 double) - data on column 9
load errors; % a array containing the error indexes (1x5590 double)
x = 1:size(consumer,1)'; % returns a (157628x1 double)
idx = (ismember(x,errors)); % returns a (157628x1 logical)
fig = plot(consumer(:,9));
hold on, plot(consumer(idx,9),'r.');
hold off
Another thing I would like to do was highlighting the whole section of the graph, like a "patch" on the same sections. Any ideas?
The trouble is that you are only providing the y-axis data to the plot function. By default, this means all data is plotted on the 1:numel(y) x locations of your plot, where y is your y-axis data.
You have 2 options...
Also provide x-axis data. You've already got the array x anyway!
figure; hold on;
plot(x, consumer(:,9));
plot(x(idx), consumer(idx,9), 'r.');
Aside: I'm slightly confused why you create idx. If errors is as you describe it (indexes of the array) then you should just be able to use consumer(errors,9).
Make all data which you don't want to appear equal to NaN. Because of the way you're loading your error indices in, this is less quick and easy. Basically you'd copy consumer(:,9) into a new variable, and index all undesirable points to set them equal to NaN.
This method has the benefit of breaking up discontinuous sections too.
y = consumer(:,9); % copy your y data before changes
idx = ~ismember(x, errors); % get the indices you *don't* want to re-plot
y(idx) = NaN; % Set equal to NaN so they aren't plotted
figure; hold on;
plot(x, consumer(:,9));
plot(x, y, 'r'); % Plot all points, NaNs wont show

Reset ColorOrder index for plotting in Matlab / Octave

I have matrices x1, x2, ... containing variable number of row vectors.
I do successive plots
figure
hold all % or hold on
plot(x1')
plot(x2')
plot(x3')
Matlab or octave normally iterates through ColorOrder and plot each line in different color. But I want each plot command to start again with the first color in colororder, so in default case the first vector from matrix should be blue, second in green, third in red etc.
Unfortunately I cannot find any property related to the color index niether another method to reset it.
Starting from R2014b there's a simple way to restart your color order.
Insert this line every time you need to reset the color order.
set(gca,'ColorOrderIndex',1)
or
ax = gca;
ax.ColorOrderIndex = 1;
see:
http://au.mathworks.com/help/matlab/graphics_transition/why-are-plot-lines-different-colors.html
You can shift the original ColorOrder in current axes so that the new plot starts from the same color:
h=plot(x1');
set(gca, 'ColorOrder', circshift(get(gca, 'ColorOrder'), numel(h)))
plot(x2');
You can wrap it in a function:
function h=plotc(X, varargin)
h=plot(X, varargin{:});
set(gca, 'ColorOrder', circshift(get(gca, 'ColorOrder'), numel(h)));
if nargout==0,
clear h
end
end
and call
hold all
plotc(x1')
plotc(x2')
plotc(x3')
Define a function that intercepts the call to plot and sets 'ColorOrderIndex' to 1 before doing the actual plot.
function plot(varargin)
if strcmp(class(varargin{1}), 'matlab.graphics.axis.Axes')
h = varargin{1}; %// axes are specified
else
h = gca; %// axes are not specified: use current axes
end
set(h, 'ColorOrderIndex', 1) %// reset color index
builtin('plot', (varargin{:})) %// call builtin plot function
I have tested this in Matlab R2014b.
I found a link where a guy eventually solves this. He uses this code:
t = linspace(0,1,lineCount)';
s = 1/2 + zeros(lineCount,1);
v = 0.8*ones(lineCount,1);
lineColors = colormap(squeeze(hsv2rgb(t,s,v)))
ax=gca
ax.ColorOrder = lineColors;
Which should work for you assuming each of your matrices has the same number of lines. If they don't, then I have a feeling you're going to have to loop and plot each line separately using lineColors above to specify an RBG triple for the 'Color' linespec property of plot. So you could maybe use a function like this:
function h = plot_colors(X, lineCount, varargin)
%// For more control - move these four lines outside of the function and make replace lineCount as a parameter with lineColors
t = linspace(0,1,lineCount)'; %//'
s = 1/2 + zeros(lineCount,1);
v = 0.8*ones(lineCount,1);
lineColors = colormap(squeeze(hsv2rgb(t,s,v)));
for row = 1:size(X,1)
h = plot(X(row, :), 'Color', lineColors(row,:), varargin{:}); %// Assuming I've remembered how to use it correctly, varargin should mean you can still pass in all the normal plot parameters like line width and '-' etc
hold on;
end
end
where lineCount is the largest number of lines amongst your x matrices
If you want a slightly hacky, minimal lines-of-code approach perhaps you could plot an appropriate number of (0,0) dots at the end of each matrix plot to nudge your colourorder back to the beginning - it's like Mohsen Nosratinia's solution but less elegant...
Assuming there are seven colours to cycle through like in matlab you could do something like this
% number of colours in ColorOrder
nco = 7;
% plot matrix 1
plot(x1');
% work out how many empty plots are needed and plot them
nep = nco - mod(size(x1,1), nco); plot(zeros(nep,nep));
% plot matrix 2
plot(x2');
...
% cover up the coloured dots with a black one at the end
plot(0,0,'k');

Plotting rows of points in Matlab

So I'm still getting used to Matlab and am having a bit of trouble with plotting. I have a cell which contains a list of points in each row. I want to plot each row of points in a different colour on the same graph so I can compare them. The catch is that I need to make this work for an unknown number of points and rows (ie the number of points and rows can change each time I run the program).
So for example, I might have my cell array A:
A = {[0,0], [1,2], [3,4]; [0,0] [5,6], [9,2]}
and I want to plot the points in row 1 against their index (so a 3D graph) and then have the points in row 2 on the same graph in a different colour. The rows will always be the same length. (Each row will always have the same number of points). I've tried a few different for loops but just can't seem to get this right.
Any help in sending me in the right direction would be greatly appreciated!
The fact that the number of points and rows can change with each iteration should not pose much of a problem. I would suggest using the size function before your plot loops (size(A,1) and size(A,2)) to get the dimensions of the matrix.
Once you have the size of the matrix, loop through the dimensions and plot the lines on the same plot using holdon, and then finally just make the line color a function of the dimensions as you loop through so that you always have a different line color
You could just convert it to a matrix and plot it directly:
% Some dummy data - format a little different from your example
% to allow for different numbers of elements per row
A = {[0,0, 1,2, 3,4]; [0,0, 5,6]};
% Figure out how many columns we need in total
maxLen = max(cellfun(#length, A));
% Preallocate
Amat = NaN(size(A, 1), maxLen);
% Copy data
for n = 1:size(A, 1)
curA = A{n};
Amat(n, 1:length(curA)) = curA;
end
% Generate 1:N vector repeated the correct number of times (rows)
x = repmat(1:size(Amat, 2), size(Amat, 1), 1);
plot(x, Amat)
Edit: You mentioned a 3D graph at some point in your post. The above won't plot a 3D graph, so here's something that will:
% Generate Amat as above
% Then:
[X, Y] = meshgrid(1:size(Amat, 1), 1:size(Amat, 2));
surf(X, Y, Amat.'); % OR: plot3(X, Y, Amat.');
I'm not sure this is exactly what you want, but your question is slightly unclear on exactly what kind of graph you want out of this. If you just want coloured lines on your plot, you can use plot3 instead of surf, but IMHO surf will probably give you a clearer plot for this kind of data.

How to plot two figures in MATLAB

I am implementing a clustering algorithm for n data points and I want to plot n data points in a figure before clustering and in another figure after clustering meaning that there should be two figures in same file with same data points.
My code is like:
X = 500*rand([n,2]);
plot(X(:,1), X(:,2), 'r.') 1
%Some coding section here
After:
symbs = {'r+','g.','bv','m*','ko'};
hold on
for i = 1: length(I)
plot(X(C==i,1), X(C==i,2), symbs{i}) 2
end
I just want to plot (1) in one figure and (2) in another.
Try subplot:
figure;
subplot(1,2,1)
plot(firstdata)
subplot(1,2,2)
plot(seconddata)
This will create two axes areas within the same figure window... from your description, this is my best guess as to what you want.
Edit: From the comments below, here is what you are doing
n=50;
X = 500*rand([n,2]);
subplot(1,2,1); #% <---- add 'subplot' here
plot(X(:,1),X(:,2),'r.')
symbs= {'r+','g.','bv','m*','ko'};
subplot(1,2,2); #% <---- add 'subplot' here (with different arguments)
hold on
for i = 1: length(I)
plot(X(C==i,1),X(C==i,2),symbs{i})
end
If all you want is a second figure window, instead of doing subplot you can simply say figure in the place where I put the second call to subplot and a new figure window will be created.
figure; #% <--- creates a figure window
n=50;
X = 500*rand([n,2]);
plot(X(:,1),X(:,2),'r.') #% <--- goes in first window
symbs= {'r+','g.','bv','m*','ko'};
figure; #% <---- creates another figure window
hold on
for i = 1: length(I)
plot(X(C==i,1),X(C==i,2),symbs{i}) #% <--- goes in second window
end
You just need to add figure before each plot to get two plots in two separated figures