Plot means over grouped boxplot in MATLAB? - matlab

I am using multiple_boxplot function to generate grouped boxplots:
http://au.mathworks.com/matlabcentral/fileexchange/47233-multiple-boxplot-m
However, instead of medians I want to plot means. First I tried general method:
plot([mean(x)],'dg');
But it did not work. I tried to extract the means and then plot them but that also is not working.
m=[];
for i=1:max(group)
idx=find(group==i);
m=[m nanmean(x(idx))];
end
boxplot(x,group, 'positions', positions);hold on
plot([m],'dg')
What am I doing wrong? And how to plot the means with each boxplot?
Thanks.

You can do the following:
In the function multiple_boxplot change line 48 to:
B = boxplot(x,group, 'positions', positions);
and change the header of the function to:
B = multiple_boxplot(data...
and save the function file.
This won't change anything in how the function works but will let you obtain a handle to the boxplot (B).
Then in your code, create the boxplot as before, but with the output argument B:
B = multiple_boxplot(data...);
And add the following lines:
% compute the mean by group:
M = cellfun(#mean,data);
% convert it to pairs of Y values:
M = mat2cell(repmat(M(:),1,2),ones(size(M,1),1),2);
% change the medians to means:
set(B(6,:),{'YData'},M)

Related

How can I build custom xticklabels using numbers and strings?

I am trying to customize the Xticklabels of my bar graph to have a format of 'number (units)'
So far I have a vector:
scanrate = [2;4;6;8;10];
I want my bar graph to have an x axis of:
2mv/s 4mv/s 6mv/s 8mv/s 10mv/s
If I use xticklabels(num2str(scanrate))
the xticklabels change to the numbers in the scanrate vector. I want to put mv/s after each Xtick.
You can also use strcat :
xticklabels(strcat(num2str(scanrate),' mv/s'))
Please note that it works only when scanrate is a column vector.
Fun fact :
num2str(scanrate) + " mv/s"
also works, but
num2str(scanrate) + ' mv/s'
does not
Build your strings using sprintf(), where the %d flag is for an unsigned integer:
my_labels = {};
for ii = 1:numel(scanrate)
my_labels{ii} = sprintf('%dmv/s', scanrate(ii));
end
figure;
% (...) make your plot
xticklabels(my_labels)
Alternative one-liner, thanks to Wolfie's comment:
my_labels = arrayfun(#(x)sprintf('%dmv/s',x),scanrate,'uni',0);
As a side note: that's normally not what you'd do when creating these type of plots. You'd just have numbers on the axes and a label stating something as "Velocity [mv/s]", rather than having the unit on every single tick label.

Modify multiple XTick values at once

I want to make a matrix of scatterplots in Matlab (version R2014b), and have only two ticks (minimum and maximum) for each x and y axis because the real world example has more plots and that will be easier to read. Here is an example, and as you can see, the second for loop isn't working as intended to edit the ticks. Also, is there a way to set this without a for loop?
% Example data
example = [ -5.2844 5.0328 307.5500
-12.0310 5.1611 237.9000
-15.9510 7.5500 290.7600
-11.5500 13.6850 285.8400
-1.9356 9.4700 273.2600
-9.2622 4.7456 232.6000
-6.5639 5.2272 265.3800
-4.4795 14.8320 281.1300
-2.1474 13.0690 288.7300
-3.7342 11.7450 265.2200
-11.9040 10.9660 286.5700
-2.1789 6.7442 258.9700
-2.8316 11.8210 281.7500
-2.6170 7.4740 244.8600
-6.8770 1.6623 116.9800
-10.2210 5.7575 300.2200
-3.9430 5.9715 253.6000
-3.3690 5.6530 230.9700
2.6090 3.2750 236.8700
-5.1430 8.4060 273.9600
-7.9360 2.7855 254.8200
-2.8665 2.0241 176.0600
-0.0960 3.3165 228.6800
-8.8465 10.3240 289.2100
-8.1930 16.4070 289.7000
-6.5840 13.4010 283.2600
2.2405 8.4625 270.1000
-2.2505 7.5555 285.9100
-4.6955 6.2985 279.2000
-0.7610 12.5210 283.2000
-0.7510 9.9470 279.9100
1.7120 8.5990 285.5700
-0.6245 7.6905 251.9100
-19.2320 6.8545 306.2700
-4.1255 9.8265 298.2000
2.9486 3.8881 250.2100
1.7333 5.5000 240.7300
-6.5881 3.9152 234.3800
-7.9543 8.0771 276.8000
-6.9641 8.8573 284.2800
-10.3280 7.4768 291.8700
-8.0818 5.1250 250.6600
-10.1490 3.9427 271.0000
-2.7786 3.7673 213.6500
-14.5410 11.1500 288.9100
-6.8118 11.0210 280.2000
-2.6459 6.5127 213.2600
1.4036 4.2023 253.9400
-5.0014 9.3900 267.0600
-9.7382 12.0990 290.8800]
% Labels for data
data_labels = {'Variable1','Variable2',...
'Variable3'};
% Make scatterplot matrix with histogram on diagonal
figure()
[H,AX]= plotmatrix(example(:,:));
% label the axes of the plots (rotated) works fine
for i = 1:length(AX)
ylabel(AX(i,1),data_labels{i},'Rotation',0,'HorizontalAlignment','right',...
'FontSize',12);
xlabel(AX(end,i),data_labels{i},'Rotation',60,'HorizontalAlignment','right',...
'FontSize',12);
end
% Set ticks (not working yet)
NumTicks = 2;
for i = 1:length(AX)
L = get(AX(i,i),'XLim');
set(AX(i,i),'XTick',linspace(L(1),L(2),NumTicks));
% set y ticks here too
end
You are incorrectly using i or both subscripts when indexing into AX.
AX(i) % Rather than AX(i,i)
Also, it's better to use numel than length and use a variable rather than i as your loop variable (since that's a MATLAB built-in for 0 + 1i). Also, you can use a single linear index into AX rather than specifying row and column subscripts.
for k = 1:numel(AX)
L = get(AX(k),'XLim');
set(AX(k),'XTick',linspace(L(1),L(2),NumTicks));
end
If you want to do this witnout a loop, you could technically do it using cellfun and the fact that you can set the same property in multiple plot objects using the following syntax
set(array_of_plot_handles, {'Property'}, array_of_values_to_set)
So applied to your problem, it would be something like
% Get all XLims as a cell array
oldlims = get(AX, 'XLim');
% Compute the new xlims
newlims = cellfun(#(x)linspace(x(1), x(2), NumTicks), oldlims, 'UniformOutput', false);
% Now set the values
set(AX, {'XTick'}, newlims);
Or if you really want it to be one line
set(AX, {'XTick'}, cellfun(#(x)linspace(x(1),x(2),NumTicks), get(AX, 'Xlim'), 'UniformOutput', false))

Matlab Function and Input

function area = traparea(a,b,h)
% traparea(a,b,h) Computes the area of a trapezoid given
% the dimensions a, b and h, where a and b
% are the lengths of the parallel sides and
% h is the distance between these sides
% Compute the area, but suppress printing of the result
area = 0.5*(a+b)*h;
This is just an example. I would like to know how to declare the values suppose a=5,b=4,h=8 in a seperate .m file and calling it into original function ie, traparea, using .in statement?
for example
.in a=5
like that
Please help
If I understand, you want to create a script file. Create a filename called "myscript.m" (pick any name you like), and place it in the same folder as "traparea.m" is located. Then, in the file "myscript.m", put the following:
a = 5;
b = 4;
h = 8;
result = traparea(a,b,h) % this is one way to show the result
fprintf('my result is %f\n', result); % this is another way to display the result
Once you have created the two files "myscript.m", and "traparea.m", you just type "myscript" at the command line.

Count strings occurrences and plot histogram

Is there any straightforward way to create a histogram from a cell array like the one below? The spacing between the consecutive bars should be exactly the same and the labels of the x-axis should be the corresponding names of the variables below in a vertical orientation.
'w464'
'w462'
'w461'
'w464'
'w461'
'w463'
'w466'
'w461'
I would like to know a better way, as well. Fwiw, I have used countmember in a roundabout way to plot data like this. I.E. if the data you posted was named A
>> B={sort(unique(A)) countmember(sort(unique(A)),A)};
>> bar(B{2});
>> set(gca,'XTickLabel',B{1})
If you have access to the statistics toolbox, grp2idx is very useful:
%# sorting is only necessary if the output should be sorted as well
[idx,label] = grp2idx(sort(A))
hist(idx,unique(idx));
set(gca,'xTickLabel',label)
A solution that only uses built-in functions
[u,~,n] = unique(A(:));
B = accumarray(n, 1, [], #sum);
bar(B)
set(gca,'XTickLabel',u)
You can also use the histogram function as follows:
[C,~,ic] = unique(A);
fig1 = figure;
axes1 = axes('Parent',fig1,'XTickLabel',C,'XTick',1:length(C));
hold(axes1,'on');
histogram(ic)

MATLAB - Labeling Curves During Iteration

I want to show the p value that was used to generate each curve next to each of the curves plotted. Note that since there is a plot of E and -E, the same p value should be next to both. I've been attempting this for a while and I have not come across anything super useful.
t = -3.1;%coupling
a = 1;%distance between r1 and r3
n = 5;%latice vector span in a1 direction
m = 1;%latice vector span in a2 direction
i = -7;%unique axial vector t_hat direction
j = 11;%unique axial vector c_hat direction
max_p = abs((n*(i+j/2)-j*(m+n/2)));%# of unique p values
La = sqrt(3)*sqrt(m^2+n*m+n^2)*a/gcd(2*n+m,2*m+n);%unit cell length
C = sqrt(n^2+n*m+m^2);%circumference of the nanotube
hold on;
for p=0:1:max_p
kt = -pi/La:.05:pi/La;
kc = 2*pi*p/C;
ka1 = kc*a*.5*(2*n+m)/C + kt*a*sqrt(3)*.5*m/C;
ka2 = kc*a*.5*(n+2*m)/C - kt*a*sqrt(3)*.5*n/C;
E = abs(t+t*exp(1i*ka2)+t*exp(1i*ka1));
title_ = sprintf('(%d,%d) Carbon Nanotube Dispersion Diagram',n,m);
title(title_);
xlabel('k_{t}a');
ylabel('Energy (eV)');
plot(kt,E);
plot(kt,-E);
end
There is a command named text that writes comments into the figures,
http://www.mathworks.se/help/techdoc/ref/text.html
with if you can't solve it with that and the to string operation i misunderstood the question
First, do you need to plot both E and -E? Since these are the same except for their sign you don't really add any information to the plot by having -E there as well. However, if you do need both lines, then just construct an array of strings for the legend, during the loop, which has each string included twice (once for E and once for -E).
... Initial calculations ...
hold on;
for p=0:1:max_p
kt = -pi/La:.05:pi/La;
kc = 2*pi*p/C;
ka1 = kc*a*.5*(2*n+m)/C + kt*a*sqrt(3)*.5*m/C;
ka2 = kc*a*.5*(n+2*m)/C - kt*a*sqrt(3)*.5*n/C;
E = abs(t+t*exp(1i*ka2)+t*exp(1i*ka1));
plot(kt,E);
plot(kt,-E);
% Construct array containing legend text
legend_text{2*(p+1)-1} = strcat('p=', num2str(p));
legend_text{2*(p+1)} = strcat('p=', num2str(p));
end
title_ = sprintf('(%d,%d) Carbon Nanotube Dispersion Diagram',n,m);
title(title_);
xlabel('k_{t}a');
ylabel('Energy (eV)');
legend(legend_text)
I am sure there is a more elegant way of constructing the legend text, but the above code works. Also, notice that I moved the calls to xlabel, ylabel and title to outside of the loop. This way they are only called once and not for each iteration of the loop.
Finally, you need to take care to ensure that each iteration of the loop plots with a different line colour or line style (see edit below). You could colour/style each pair of E and -E lines the same for a given iteration of the loop and just display the legend for E (or -E), which would obviously halve the number of legend entries. To do this you will need to hide one of line's handle visibility - this prevents it from getting an item in the legend. To do this use the following in your loop:
plot(kt, E);
plot(kt,-E, 'HandleVisibility', 'off');
% Construct array containing legend text
legend_text{p+1} = strcat('p=', num2str(p));
Finally, it is best to include clear all at the top of your Matlab scripts.
Edit: To have each plotted line use a different colour for each iteration of your loop use something like the following
... initial calculations ...
cmap = hsv(max_p); % Create a max_p-by-3 set of colors from the HSV colormap
hold on;
for p = 0:1:max_p
plot(kt, E, 'Color', cmap(p,:)); % Plot each pair of lines with a different color
plot(kt, -E, 'Color', cmap(p,:));
end