I need to produce a X vs Y graph and make a distinction between positive class and negative class (indicated in original data infile). How do I produce a legend in such a graph? This is my code for the graph right now :
infile = fopen('ClassData1.txt','r');
data = textscan(infile,'%f %f %f');
parameters = [data{1} data{2}];
label = [data{3}];
h = ones(100,9);
g = ones(100,9);
score1= ones(1,9);
sc = 0;
figure
for i = 1:100
if label(i)>0
plot(parameters(i,1),parameters(i,2),'r*')
hold on
else
plot(parameters(i,1),parameters(i,2),'b*')
end
end
To show each line type only once, you have to keep the handles. Storing only one handle per class is sufficient.
h=nan(2,1)
for i = 1:100
if label(i)>0
h(1)=plot(parameters(i,1),parameters(i,2),'r*')
hold on
else
h(2)=plot(parameters(i,1),parameters(i,2),'b*')
end
end
legend(h)
There are (more than) two ways to do this. Firstly, you can just use a single plot command and do the legend normally, by combining the plot definitions using logical indexing, or you can use the DisplayName property for each plot to give information about the legend.
% Some sample data
parameters=rand(100,2);
label=parameters(:,1)-0.5;
% Use logical indexing to replace the for loop and use a single plot command
figure(1)
plot(parameters(label>0,1),parameters(label>0,2),'r*',parameters(label<=0,1),parameters(label<=0,2),'b*')
legend('red','blue')
% Use DisplayName to set the legend entry for each plot, then show the legend using the names given
figure(2)
plot(parameters(label>0,1),parameters(label>0,2),'r*','DisplayName','Red')
hold on
plot(parameters(label<=0,1),parameters(label<=0,2),'b*','DisplayName','Blue')
hold off
legend('show')
Related
I currently want to have the legend of graph, however i'm plotting several lines that should be group in only 3 types.
My currently option is to use a dummy plot out of the boundaries, plotting the relevant data and calling the legend just at the end. It works but it is prone to errors. I wanted to update the legend and select just a few of the plots.
I tried to use the leg_handle.String, but then it comes two problems:
It still plot 5 handles instead of 3.
It does not have the proper line style & color.
Any ideas?
Bellow follow the code (with dummy plot commented) and the pictures of the current version giving the error and what i want to look.
clear
figure()
hold on
%using
%dummy plot
% leg_text={'a','b','c'};
% plot(100,100,'-r')
% plot(100,100,'-b')
% plot(100,100,'-k')
for ii=1:20,
plot(1:11,linspace(0,ii,11),'-r')
end
for ii=30:50,
plot(1:11,linspace(0,ii,11),'-b')
end
for ii=70:80,
plot(1:11,linspace(ii,25,11),'-k')
end
Yaxl=[-1 80];
Xaxl=[1 11];
set(gca, 'Visible','on', ...
'Box','on', ...
'Layer','top',...
'Xlim',Xaxl, ...
'Ylim',Yaxl);
%using
% legend(leg_text)
%want to use
leg_hand=legend(gca,'show');
leg_hand.String=leg_hand.String([1 21 42]);
%extra comand will give the things that i wanted above
% leg_hand.String=leg_hand.String([1 2 3]);
What it gives:
What I expect to have:
I have tried this method using [a,b,c,d]=legend, but this give only the a handle that i already using.
This little workaround should do the job:
clear();
figure();
hold on;
h = gobjects(3,1);
for ii = 1:20
h(1) = plot(1:11,linspace(0,ii,11),'-r');
end
for ii = 30:50
h(2) = plot(1:11,linspace(0,ii,11),'-b');
end
for ii = 70:80
h(3) = plot(1:11,linspace(ii,25,11),'-k');
end
set(gca,'Box','on','Layer','top','Visible','on','Xlim',[1 11],'Ylim',[-1 80]);
legend(h,'A','B','C');
hold off;
Actually, what I did is very simple. I created an array of graphical objects of size 3 (one for each iteration) using the gobjects function. Then, inside each iteration, I assigned the last plotted line to its respective array placeholder. Finally, I created the legend using the three graphical objects I previously stored.
Alternatively:
clear();
figure();
hold on;
h1 = gobjects(20,1);
for ii = 1:20
h1(ii) = plot(1:11,linspace(0,ii,11),'-r');
end
h2 = gobjects(21,1);
for ii = 30:50
h2(ii-29) = plot(1:11,linspace(0,ii,11),'-b');
end
h3 = gobjects(11,1);
for ii = 70:80
h3(ii-69) = plot(1:11,linspace(ii,25,11),'-k');
end
set(gca,'Box','on','Layer','top','Visible','on','Xlim',[1 11],'Ylim',[-1 80]);
legend([h1(1) h2(1) h3(1)],'A','B','C');
hold off;
You create an array of graphical objects for storing the plot handlers produced by every iteration. Then you create the legend using the first (basically, any) item of each array of graphical objects.
I need to prevent a specific plot entry from being displayed on a Matlab plot legend.
Sample:
% x and y are any plot data
for i=1:5
plot(x,y);
plot(x2,y2,'PleaseNoLegend!'); % I need to hide this from legend
end
legend('show');
Is there any flag I can set inside the plot command so this specific entry doesn't show up in legend?
You can achieve that by setting the 'HandleVisibility' property to 'off'. Note that this hides the handles of those plots to all functions, not just to legend.
For example,
hold on
for k = 1:3
x = 1:10;
y = rand(1,10);
x2 = x;
y2 = y + 2;
plot(x,y);
plot(x2,y2,'--','HandleVisibility','off'); % Hide from legend
end
legend('show')
produces the graph
You can use the semi-documented function called hasbehavior, that allows you to ignore individual plots in a legend after you issued the plot command.
figure;
hold on;
for i=1:5
plot(x,y);
h = plot(x2,y2);
hasbehavior(h,'legend',false);
end
legend('show');
The fact that it's semi-documented suggests that it could break sooner or later in a newer MATLAB version, so use with care. It might still be a convenient choice for certain applications.
As #stephematician noted, this MATLAB built-in is also unavailable in Octave, which might be another reason why the other answers are preferable.
As Luis Mendo mentions (and I somehow missed this) the handle is hidden to all other functions in his answer, which will be ok in most situations, but an alternative solution which looks identical to the above and doesn't have this effect is:
k_values = 1:3;
h = nan(size(k_values));
x = 1:10;
hold on
for k = k_values
y = rand(size(x));
y2 = y + 2;
h(k) = plot(x,y);
plot(x,y2,'--');
end
hold off
legend(h, strcat('data', num2str(k_values')))
The final command sets the legend entry for each handle returned by the plot(x,y) command. The first argument is a 1x3 array of line handles which will appear in the legend, and the second argument is a 3x5 char matrix where each row is a label.
I would like to visualize different responses of different systems in a single plot with Matlab's control toolbox, and to colorize the various curves so it is easy to differentiate between the different systems.
The response plots are easily created using the control toolbox - e.g. step response (using step), response to an arbitrary input (using lsim), etc.
When using separate model objects for different systems, It's easy to create multi-color plots, e.g., for a step response: step(Sys1, 'b', Sys2, 'r') would give one blue curve and one red cure, if Sys1 and Sys2 are both a single system model.
However, if plotting a model array, there's no way to differentiate between the various curves that belong to the same array. E.g.: step(SysArray, 'b') would make all curves blue. step(Sys,'b','r') is invalid - so no easy way to specify various colors.
Also, using the "Edit Plot" tool, selecting one curve effectively selects all curves, and any changes to the properties (e.g. line color) would affect all curves.
Is there any way to control the properties of each curve separately?
There's no built-in function to do this, so you have to roll your own functionality
% Create n-by-3 array of colours to use
coloursArray = rand(numel(stackedSystems),3); % for this example put in random colours
% Do the plot
step(stackedSystems);
title('My custom title');
grid on
% Change colours
ha = findobj(gcf,'type','axes','visible','on'); % Get handles of all axes (for MIMO responses)
for jdx = 1:numel(ha)
hl = findobj(ha(jdx),'type','line','visible','on'); % Get handles to all lines
for idx = 1:numel(hl)
set(hl(idx),'Color',coloursArray(idx,:)); % Change the colour
end
end
#Phil Goddard
There's no built-in function to do this, so you have to roll your
own functionality
% Create n-by-3 array of colours to use
coloursArray = rand(numel(stackedSystems),3); % for this example put in random colours
% Do the plot
step(stackedSystems);
title('My custom title');
grid on
% Change colours
ha = findobj(gcf,'type','axes','visible','on'); % Get handles of all axes (for MIMO responses)
for jdx = 1:numel(ha)
hl = findobj(ha(jdx),'type','line','visible','on'); % Get handles to all lines
for idx = 1:numel(hl)
set(hl(idx),'Color',coloursArray(idx,:)); % Change the colour
end
end
Thanks for the code!
Here are some slight changes to work better with model sampling through parameter variation, including the colorbar.
I was hoping it would also work with pzmap, for example, but it creates 2*n lines (poles and zeros), so it would need a bit more work.
function colorSamplingPlot(values,var)
% values is an array with parameter value assigned to each curve
% var is a string for the colorbar label
n = numel(findobj(gca,'type','line','visible','on'));
% Create n-by-3 array of colours to use
coloursArray = colormap(jet(n));
% Change colours
% Get handles of all axes (for MIMO responses)
ha = findobj(gcf,'type','axes','visible','on');
for jdx = 1:numel(ha)
% Get handles to all lines
hl = findobj(ha(jdx),'type','line','visible','on');
for idx = 1:numel(hl)
% Change the color; inverted color order to match colorbar
set(hl(idx),'Color',coloursArray(numel(hl)-idx+1,:));
end
end
colorbar;
caxis([min(values),max(values)]);
hcb = colorbar;
hcb.Label.String = vars;
end
I want to visualize two sets of data in different figures. Here is how do I realize it now:
f1 = figure;
for i=0:6
plot(stim(i)+i);
hold on;
end;
f2 = figure;
for i=0:6
plot(data(i)+i);
hold on;
end;
I think there have to be the way to combine these loops.
Sure. As per Matlab reference: first you create empty figures and do the hold-on (you don't need to do it every time):
f1 = figure;
hold on
f2 = figure;
hold on
Then you loop:
for i=0:6
figure(f1)
plot(stim(i)+i);
figure(f2)
plot(data(i)+i);
end
This time the figures are already created; calling figure here therefore switches the active figure so you can plot on it;
And without for loops, something like this:
idx = (0:6).';
figure(f1);
plot(stim(idx)+idx);
figure(f2);
plot(data(idx)+idx);
Make sure that you apply the solution to the right dimension. The column vectors are interpreted as one dataset; And for points, remember to set the markers.
I'm very very new to Matlab and I tried to attempt at making a simple iteration script.
Basically all I wanted to do was plot:
1*sin(x)
2*sin(x)
3*sin(x)
...
4*sin(x)
And this is the program that I wrote:
function test1
x=1:0.1:10;
for k=1:1:5;
y=k*sin(x);
plot(x,y);
end % /for-loop
end % /test1
However, it only plots y=5*sin(x) or whatever the last number is...
Any ideas?
Thanks!
Amit
You need to use the command hold on to make sure that the plot doesn't get erased each time you plot something new.
function test1
figure %# create a figure
hold on %# make sure the plot isn't overwritten
x=1:0.1:10;
%# if you want to use multiple colors
nPlots = 5; %# define n here so that you need to change it only once
color = hsv(nPlots); %# define a colormap
for k=1:nPlots; %# default step size is 1
y=k*sin(x);
plot(x,y,'Color',color(k,:));
end % /for-loop
end % /test1 - not necessary, btw.
EDIT
You can also do this without a loop, and plot a 2D array, as suggested by #Ofri:
function test1
figure
x = 1:0.1:10;
k = 1:5;
%# create the array to plot using a bit of linear algebra
plotData = sin(x)' * k; %'# every column is one k
plot(x,plotData)
Another option would be to use the fact the plot can accept matrices, and treats them as several lines to plot together.
function test1
figure %# create a figure
x=1:0.1:10;
for k=1:1:5;
y(k,:)=k*sin(x); %# save the results in y, growing it by a row each iteration.
end %# for-loop
plot(x,y); %# plot all the lines together.
end %# test1