How to change the axes labels on a boxplot - matlab

When using the boxplot command from Statistics toolbox, the axes properties change in a strange way. For example, one gets
XTick = []
XTickLabel =
XTickLabelMode = manual
XTickMode = manual
What is happening to the axes and how one can rename the labels, and/or drop some of the ticks?

Try calling boxplot using the optional labels parameter.
Edit - further information about what boxplot actually does.
boxplot does some complicated stuff - type edit boxplot to take a look through the code, and you'll see it's a very long and intricate function. Basically it makes a blank axis with no axis labels, which is why you're seeing empty values for XTick etc. Then it makes the boxplot elements out of individual lines, and it simulates fake axis labels by adding text elements. You can find them and modify them directly by plotting into a figure f, then getting the Children of f, then iterating through to get their Children. Eventually you'll find text elements with the label names.

Try this:
xtix = {'A','B','C'}; % Your labels
xtixloc = [1 2 3]; % Your label locations
set(gca,'XTickMode','auto','XTickLabel',xtix,'XTick',xtixloc);
For some reasons resetting XTickMode to auto seemed to be key.

Thank you, Sam Roberts, that was helpful.
I wrote the following to remove group labels based on this advice. However, it removes ALL the labels, including axis and data tips. There doesn't seem to be a way to remove a label on an axis but leave it on a data tip.
m = get(get(get(figH,'Children'),'Children'),'Children');
for ii = 1:numel(m)
if(strcmp(get(m(ii),'Type'),'text'))
set(m(ii),'String', '');
end
end
The variable figH is the handle to your figure. You can also try gcf if the boxplot is the active figure handle.

Related

Hide MATLAB legend entries for some graphical objects in plots

MATLAB legends list everything in a plot, including guidelines that you have put on a plot.
A fudge to get around that is to do
*Plot
*Add legend
*Add guidelines
However, MATLAB puts the most recent lines in the front, meaning the guidelines then sit over the displayed data; ugly and distracting.
Similar problems occur any time you build up a complicated plot, legend freaks out and grabs everything, and workarounds with plotting order can be ugly
Example code:
%**** Optional guidelines
figure(1)
plot([2 2],[0,1],'k--'); hold on
%**** DATA
N = 4;
y=rand(5,N);
x=1:1:5;
for plotLoop=1:N;
%* Plot
figure(1)
plot(x,y(plotLoop,:));
hold on
end
%*****LEGEND
hLegend = legend(LegTxt,...
'interpreter','latex',...
'location','eastoutside')
(move the code block order to replicate the situations mentioned above)
How to reasonably fix this?
If you want a certain graphics object to not produce a legend (and that will work even if you toggle the legend off and on again), you can modify the LegendInformation:
%# plot something that shouldn't show up as legend
handleWithoutLegend = plot(something);
%# modify the LegendInformation of the Annotation-Property of the graphical object
set(get(get(handleWithoutLegend,'Annotation'),'LegendInformation'),...
'IconDisplayStyle','off');
%# toggle legend on and off at will, and never see the something-object appear
If you try to turn off the legend on an array of handles, the best way is just to loop over them, with a try-wrapper for graphical objects that cannot produce a legend:
for h = listOfHandles(:)'
try
set(get(get(h,'Annotation'),'LegendInformation'),...
'IconDisplayStyle','off');
end
end
Craft a custom handle that you feed into the legend. Plot handles can be concatenated to form an object that legend is happy to accept as input.
The required code isn't pretty, but it does work.
%**** Optional guidelines for periodicity
figure(1)
plot([2 2],[0,1],'k--'); hold on
%**** DATA
N = 4;
y=rand(5,N);
x=1:1:5;
for plotLoop=1:N;
LegTxt{plotLoop} = num2str(plotLoop);
%* Plot
figure(1)
% if statement to construct a handle for the legend later
if plotLoop==1
htot=plot(x,y(plotLoop,:));
else
h=plot(x,y(plotLoop,:));
% Append this info to the figure handle
htot= [htot, h];
end
hold on
end
%*****LEGEND
hLegend = legend(htot,LegTxt,...
'interpreter','latex','FontSize',16,...
'location','eastoutside')
For the pedantic or curious, the loop for plotLoop=1:N; is here because I extracted the example from some rather complex code where the data is extracted from cell arrays. Obviously you could eliminate that loop for a lot of usage scenarios, I just decided to keep the code in its most flexible format!
You can also hide plot from legend in another way. Here's the sample:
figure(1)
hold on
x=1:10;
y1=x;
y2=x.^2/10;
y3=x.^3/100;
plot(x,y1);
plot(x,y2,'HandleVisibility','off');
plot(x,y3);
legend('x','x^3')
You just need to put 'HandleVisibility', 'off' to your plot that you don't want to show up in legend. That's how result looks like:
HandleVisibility is a line property so it might now work if you create plot in some other way. But for most use cases its enough and it is much simpler.

Plotting, marking and legend in a loop

I want to plot a graph, mark a point and write legend in a loop.
labels = {}
for i = 1: size(error,1)
r = plot(handles.axes1,temp(i).time,temp(i).signal);
hold (handles.axes1, 'on')
a = %find minimum index
xmin = temp(i).time(a);
ymin = temp(i).signal(a);
plot(handles.axes1,xmin,ymin,'ro')
labels{end+1} = sprintf('Type : %s, %f,%f',error{i,1}.main(1,1).type,xmin,ymin)
end
grid on
legend(r, labels);
Labeling does not work, as it takes only 1st elements ignoring extra element. and the whole method is a mess with color code all messed up, is there elegant way of doing this where my legend colour matches the plot ones
Another way to do this is to use the DisplayName keyword.
for i = 1:N_lines
%...
r(i) = plot(handles.axes1, temp(i).time, temp(i).signal, 'DisplayName', labels{i});
%...
end
legend('show')
The advantage of doing it like this is that it attaches the name directly to the plotted point. If you are debugging, and open the plot as its being written in the plot browser, as each point get plotted the name will appear next to the point in the right-hand pane. You also don't need to keep track of a separate labels variable in case you end up later reordering your points for some reason. This way the labels always travel with their associated points.
I should add that when you call the legend command with a cell of labels, among other things it backfills 'DisplayName' so that you can still change and query it after the plot has been built even if you don't explicitly set it like I've done above. However, I find this method to be self-documenting and more convenient because it's one less thing to keep track of.
You need to make r an array. As it is, you're only storing the last plot handle so when you call legend it's only going to use the last plot and the first label.
% Create a unique color for each plot
colors = hsv(size(error, 1));
for i = 1:size(error, 1)
r(i) = plot(handles.axes1,temp(i).time,temp(i).signal, 'Color', colors(i,:));
%...
labels{i} = sprintf('Type : %s, %f,%f',error{i,1}.main(1,1).type,xmin,ymin);
end
legend(r, labels)
As a side-note it's best to not use i or j as your looping variable and also, don't name your variable error as that's the name of a MATLAB built-in.

Creating annotation boxes for subplots in a for-loop in Matlab

I have the following code in Matlab that runs through a for loop, reads data from a file and plots 9 different figures, that correspond to some particular "channels" in my data, so I decided to annotate them in the for loop.
clear
clc
for i=1:9
subplot(3,3,i);
hold on
x = [4 13]; % from your example
y = ([1 1]); % from your example
y2 = ([-0.4 -0.4]);
H=area(x,y,'LineStyle','none',...
'FaceColor',[1 0.949019610881805 0.866666674613953]);
H1=area(x,y2,'LineStyle','none',...
'FaceColor',[1 0.949019610881805 0.866666674613953]);
% Create textbox
annotation('textbox',...
[0.719849840255583 0.603626943005185 0.176316293929713 0.308290155440411],...
'String',{'FABLIGHT04','Channel',i},...
'FontWeight','bold',...
'FontSize',10,...
'FontName','Geneva',...
'FitBoxToText','off',...
'EdgeColor','none');
axis([0 24 -0.4 1])
set(gca,'XTick',[0:1:24])
set(gca,'YTick',[-0.4:0.2:1])
xlabel('Time (s)');
end
Initially it was giving me 9 different figures and the annotation thing worked fine. But I wanted to be able to tile them onto a subplot for easier comparison.
Since I switched over to using subplot, it does not annotate my figure properly. On opening the editing dock and generating the code, I find that matlab is plotting everything first and then just putting the annotation boxes in the same figure, one on top of the other. Looking at the code it generated, it apparently takes this part of the code:
annotation('textbox',...
[0.719849840255583 0.603626943005185 0.176316293929713 0.308290155440411],...
'String',{'FABLIGHT04','Channel',i},...
'FontWeight','bold',...
'FontSize',10,...
'FontName','Geneva',...
'FitBoxToText','off',...
'EdgeColor','none');
and does it as:
annotation(figure1,'textbox'...)
etc etc
So for all 9 text boxes, it puts them onto the same figure. I tried to do S=subplot(3,3,i) then annotation(S,'textbox') etc etc, I have also tried S(i)=subplot(3,3,i) and then annotation(S,'textbox') etc etc but nothing seems to work.
I have also tried to change the location of the box. I can't seem to figure out how to make it smaller either.
Does anyone know how to have annotation boxes in the right subplot in a for loop?
Thanks
I'm afraid annotation objects are properties of figures and NOT axes, as such its harder to customize the position of each annotation objects because no matter how many subplots you have, they are all part of the same figure and you need to specify their position relatively to the figure coordinate system.
Therefore, you can manually set the position of each text box in your code depending on the subplot it belongs to...
Simple example:
clear
clc
close all
figure('Units','normalized'); %// new figure window
for k = 1:2
str = sprintf('Subplot %d',k);
subplot(1,2,k)
plot(rand(1,10));
%// Customize position here
hAnnot(k) = annotation('textbox', [k*.4-.2 .6 .1 .1],...
'String', str,'FontSize',14);
end
Which looks like this:
Its not very elegant but I'm personally not aware of any other option if you do need to use annotations objects. A less cumbersome alternative would be to use a simple text objects, which are properties of axes and therefore much more friendly to position :)
Hope that helps!

Remove Objects from Legend When You Have Also Used Fit, Matlab

I've plotted data points and fitted an exponential curve between them using 'fit' in Matlab. The problem is that with the fit-function I got the fitted line I wanted to plot, but also extra markers on top of my regular markers. I solved this problem by plotting the wanted markers on top of the unwanted so that they couldn't be seen. Now to the problem. When I want to show the legends those dots are also in there. How can I remove the markers from the legend without removing the fitted line since both of them are hidden inside the fit-function? Can I stop 'fit' from plotting the unwanted markers? So, I want to remove the blue dot called 'hoff' in the picture below.
You can leave out legend-entries by manually leaving out the handles of the lines, that you dont want to be in the legend. Try this:
%if you plot something, that you want showing up in the legend, save its handle:
h_line = plot(x,y)
%you dont want to show up this line? dont do anything, just plot it:
plot(myMarker)
%then set the legend-> you can add the text for your legend-entries with
%a cell-array containing the strings you want to show up:
legend([h_line another_line],{'Text1' 'Text2'})
with the example (see comments) I came to this solution:
close all
X=[1:10];
Y=X*0.5+0.1;
ft = fittype('poly2');
f = fit(X', Y',ft);
ha=plot(f)
hold on
hc=plot(X,Y)
hb=errorbar(X, Y, X*0.1, 'squarek','MarkerFaceColor','k','markersize',5)
hleg1 = legend([ha hc],{'hnh','ghg'});
-> this is just about splitting the plot-command. Hope that helps...
the result should look like this:

how to remove argument labels from polar plot in MATLAB

Does anyone know a simple way to remove the labels from the argument axis in a polar plot in MATLAB? My figures are small and I have to zoom in to see them, but when I do this the argument labels from one subplot get in the way of the other subplots.
Equally, if anyone knows of a way to solve this issue by rescaling the axis in the radial direction, or of any solution for that matter, then I would be very grateful. For the mean time I'll have to trim and re-size in Latex.
I tried the method here
How to remove Rho labels from Matlab polar plot?
but it didn't work.
here is some sample code
subplot(1,3,1,'align');
r = 10;
polar(t,abs((r.*exp(t.*1i) - (1+1i)).^2));
set(gca, 'fontsize', 20)
set(findall(gca, 'String', '0'),'String', ' ') %remove theta labels
hold on
Given the following example input:
t = 0:.01:2*pi;
polar(t,sin(2*t).*cos(2*t),'--r')
You can remove the vertical labels (along rho) by keeping only the legit ones.
% Find all handles to text labels
h = findall(gca,'type','text');
% Define what to keep
legit = {'0','30','60','90','120','150','180','210','240','270','300','330','360',''};
% Take the others and set them to empty string
idx = ~ismember(get(h,'string'),legit);
set(h(idx),'string','')
EDIT addressing comments
One approach would be simply setting to empty string '' those labels defined IN legit, i.e. by removing ~ near ismember. However, this approach is not robust in the sense that it will remove all of the labels that match. Suppose you have some other label with 120, then it will be removed as well.
One way to solve this issue is to edit polar() on line 155 and 162 by adding a 'Tag' to the radial annotations:
'HandleVisibility', 'off', 'Parent', cax,'Tag','spoke');
Then, save the edited function, plot, retrieve those text labels, and set to empty string:
h = findall(gca,'Type','text','-and','Tag','spoke');
set(h,'string','')