matlab bar plot: labeliing 3 bars with each only one value - matlab

I need to make a bar graph in matlab with 3 bars. The values for the three bars is stored in x. Now I want a to make a legend: Each bar should be labeled with a letter e.g. 'A','B','C'.
x = rand(1,3); bar(x); legend('A','B','C');
Did not work.
Then I tried this example: http://www.mathworks.com/matlabcentral/fileexchange/35271-matlab-plot-gallery-vertical-bar-plot/content/html/Vertical_Bar_Plot.html
But as soon as you reduce the the number of entries in each category to 1, you'll get an error message, but I think the message is wrong =/ it works with any number but just not with 1...
So is there a simple solution to that problem?

What you want is a "three series plot" - unfortunately, as soon as you make it 1x3, Matlab thinks it's just a single series. We have to trick it into thinking you have three series. Here's how you do that:
x = rand(1,3);
x2 = [x; x*0]; % add a second row of all zeros
figure
bar(x2); % now we have a plot with an ugly second category
xlim([0.5 1.5]); % trick that hides second category
legend('a','b','c'); % add the legend
set(gca, 'XTickLabel', ''); % hide the '1' on the X axis (or make it whatever you want)
title 'Bar plot with legend - demo'
Result is then something like this:
I believe this is exactly what you were asking for.

Related

How to set x and y values when using bar3 in Matlab?

Quick version
How can I control the x- and y-values for a 3-d bar plot in Matlab?
Details
Say we have an 10 x 20 data matrix and we plot it using bar3, and we want to set the x- and y-values. For instance:
foodat = rand(10,20);
xVals = [5:14];
yVals = [-3:16];
bar3(xVals, foodat);
xlabel('x'); ylabel('y');
Is there a way to feed it the yVals as well? Otherwise the y axes always defaults to [1:N].
Note I don't just want to change the labels using XTickLabel and YTickLabel. I need to change the actual values on the axes, because I am plotting multiple things in the same figure. It isn't enough to just change how the (wrong) axis ticks are labeled. So this is different from issues like this:
How can I adjust 3-D bar grouping and y-axis labeling in MATLAB?
Other things I have tried
When I try changing the xvals with:
set(gca,'XTick', xVals)
set(gca,'YTick', yVals)
The values are taken in, but actually show up on the wrong axes, so it seems x and y axes are switched using bar3. Plus, it is too late anyway as the bar graph was already plotted with the wrong x- and y-values, so we would end up giving ticks to empty values.
Note added
Matlab tech support just emailed me to let me know about the user contributed function scatterbar3, which does what I want, in a different way than the accepted answer:
http://www.mathworks.com/matlabcentral/fileexchange/1420-scatterbar3
I found a way of doing it. Ill give you a piece of code, then you'll need to "tidy up" , mainly the axis limits and the Xticks, as bar3 does set up the Xticks inside, so if you want others you'll need to set them manually yourself.
So the trick here is to get the Xdata from the bar3 handle. The thing here is that it seems that there is a handle for each row of the data, so you need to iterate for each of them. Here is the code with the current output:
foodat = rand(20,10);
xVals = [5:14];
yVals = [-3:16];
% The values of Y are OK if called like this.
subplot(121)
bar3(yVals, foodat);
subplot(122)
h=bar3(yVals, foodat);
Xdat=get(h,'XData');
axis tight
% Widdth of barplots is 0.8
for ii=1:length(Xdat)
Xdat{ii}=Xdat{ii}+(min(xVals(:))-1)*ones(size(Xdat{ii}));
set(h(ii),'XData',Xdat{ii});
end
axis([(min(xVals(:))-0.5) (max(xVals(:))+0.5) min(yVals(:))-0.5, max(yVals(:))+0.5])
Note: Y looks different but is not.
As you can see now the X values are the ones you wanted. If you'd want other size than 1 for the intervals between them you'd need to change the code, but you can guess how probably!

How to change font size of right axis of Pareto plot in Matlab

I am trying to bold the right side y axis for a Pareto plot in Matlab, but I can not get it to work. Does anyone have any suggestions? When I try to change the second dimension of ax, I get an error:
"Index exceeds matrix dimensions.
Error in pcaCluster (line 66)
set(ax(2),'Linewidth',2.0);"
figure()
ax=gca();
h1=pareto(ax,explained,X);
xlabel('Principal Component','fontweight','b','fontsize',20)
ylabel('Variance Explained (%)','fontweight','b','fontsize',20)
set(ax(1),'Linewidth',2.0);
set(ax(1),'fontsize',18,'fontweight','b');
%set(ax(2),'Linewidth',2.0);
%set(ax(2),'fontsize',18,'fontweight','b');
set(h1,'LineWidth',2)
Actually you need to add an output argument during the call to pareto and you will then get 2 handles (the line and the bar series) as well as 2 axes. You want to get the YTickLabel property of the 2nd axes obtained. So I suspect that in your call to pareto above you do not need to supply the ax argument.
Example:
[handlesPareto, axesPareto] = pareto(explained,X);
Now if you use this command:
RightYLabels = get(axesPareto(2),'YTickLabel')
you get the following (or something similar):
RightYLabels =
'0%'
'14%'
'29%'
'43%'
'58%'
'72%'
'87%'
'100%'
What you can do is actually to erase them altogether and replace them with text annotations, which you can customize as you like. See here for a nice demonstration.
Applied to your problem (with dummy values from the function docs), here is what you can do:
clear
clc
close all
y = [90,75,30,60,5,40,40,5];
figure
[hPareto, axesPareto] = pareto(y);
%// Get the poisition of YTicks and the YTickLabels of the right y-axis.
yticks = get(axesPareto(2),'YTick')
RightYLabels = cellstr(get(axesPareto(2),'YTickLabel'))
%// You need the xlim, i.e. the x limits of the axes. YTicklabels are displayed at the end of the axis.
xl = xlim;
%// Remove current YTickLabels to replace them.
set(axesPareto(2),'YTickLabel',[])
%// Add new labels, in bold font.
for k = 1:numel(RightYLabels)
BoldLabels(k) = text(xl(2)+.1,yticks(k),RightYLabels(k),'FontWeight','bold','FontSize',18);
end
xlabel('Principal Component','fontweight','b','fontsize',20)
ylabel('Variance Explained (%)','fontweight','b','fontsize',20)
which gives this:
You can of course customize everything you want like this.
That is because ax is a handle to the (first/left) axes object. It is a single value and with ax(1) you got lucky, its ax again, but ax(2) is simply not valid.
I suggest to read the docs about how to get the second axis. Another good idea always is to open the plot in the plot browser, click whatever object you want so it is selected and then get its handle by typing gco (get current object) in the command window. You can then use it with set(gco, ...).

Distance between axis number and axis in MATLAB figure

I struggle a little bit with overlapping axis numbers of the y and x axis like it is shown in the image. I'd like to keep the size of the numbers and therefore think that simply shifting the numbers away from the axis itself would be an appropriate way to handle this issue.
Is there a possibility to do that?
Thanks in advance,
Joe
Here is a little workaround using text annotations. Basically you clear the current XTick labels and replace them with similar labels, but you can specify the distance from the axis:
clc
clear
close all
x = 1:20;
hPlot = plot(x,sin(x));
set(gca,'xaxisLocation','top');
set(gca,'XTickLabel',[]); %// Clear current XTickLabel
ylim = get(gca,'YLim'); %// Get y limit of the plot to place your text annotations.
for k = 2:2:20
text(k,ylim(2)+0.1,num2str(k),'HorizontalAlignment','Center') %// Play with the 'ylim(1) -0.1' to place the label as you wish.
end
Giving this:
Of course now it's exaggerated and you can do the same for the y axis if you want (using the 'XLim' property of the current axis,gca).

Bar chart matlab by scalar vectors

I am trying to create a bar chart where my x axis shows only one data point, year of 2006, but for 3 different data related to 2006. I am doing the following, but I receive the
error of "X must be same length as Y."
Here is my code and I highly appreciate your help:
X=[2006] %year
% Create data for childhood disease cases
measles = [38556];
mumps = [20178];
chickenPox = [37140];
% Create a vertical bar chart using the bar function
figure;
bar(X, [measles' mumps' chickenPox'],'group');
% Set the axis limits
%axis([0 13 0 40000]);
% Add title and axis labels
title('Childhood diseases by month');
xlabel('Month');
ylabel('Cases (in thousands)');
% Add a legend
legend('Measles', 'Mumps', 'Chicken pox');
You are getting this error because X is only one element and you are using three different Y values.
I think this problem requires you to take a step back a bit. Why are you plotting all three against the same X value? If this worked as you specified, all three would be on top of each other.
Would it not be more informative to the viewer if the X-axis labeled each bar as measles, mumps or chickenPox?
Try:
bar([measles' mumps' chickenPox']);
set(gca,'XTickLabel',{'Measles','Mumps','Chicken Pox'});
Edit:
I see what you're after. You're almost correct. The problem is that since you only have one column of data, matlab assumes you DON'T want to create a group but just plot those 3 values against unique X values. So we need to trick it slightly by creating another data point.
% //Create two columns, one of them zeros
data = [[measles;mumps;chickenPox],[0;0;0]];
bar([X,X+1],data'); % //The 2007 entry will not be visible
This will create a group at 2006 and the 2007 entry will be zeros so you won't see it. You can then set your axes and such to be the same as the other charts.

How can I order items in a Matlab legend via the figure editor?

I've created a histogram with multiple sets of data. The data sets are color imgages converted to grayscale and taken over a given time period (e.g. pic 1 # time=0, pic 2 # time=5min, etc.) which is why I need the legend entries to show up in a specific order. When I put the legend in, the entries are scattered around in no specific order and I can't figure out how to get the entries switched up the way I need them.
In 2017a and higher (using part of the answer by Peter M above)
Select "Edit Plot" with the standard arrow button in the toolbar. This will allow you to select plot lines.
Select the plot line you want to appear first in the legend.
Use Ctrl-X (or whatever on OS X,Linux) to "Cut" the Plot line.
Create a new figure (File -> New -> Figure).
Use Ctrl-V (or whatever on OS X, Linux) to "Paste" the Plot line in the new figure.
"Cut" the Plot line in the new figure.
"Paste" the Plot line in the original figure.
Repeat steps 2-6 for every plot line, in the order that you want
them to appear in the legend. Right click on the legend and
"Refresh"
If you are regenerating the plot often of course it is probably a good idea to make sure that the script puts them in the correct order. Luis Mendo provided an answer here, but his answer to a slightly different wording was a little more detailed: how to change the sequence of the legend.
Pre 2017a Only! It seems that 2017a breaks this behavior, so the following trick does not work in the latest versions.
To answer your specific question, here is a neat trick if you are just doing this once in awhile on a plot that doesn't have many lines, and only want to use the Figure Editor...
Select "Edit Plot" with the standard arrow button in the toolbar. This will allow you to select plot lines.
Select the plot line you want to appear first in the legend.
Use Ctrl-X (or whatever on OS X, Linux) to "Cut" the Plot line.
Use Ctrl-V (or whatever on OS X, Linux) to "Paste" the Plot line.
Repeat steps 2-4 for every plot line, in the order that you want them to appear in the legend.
Right click on the legend and "Refresh"
You can get a handle to each plotted object, and in the legend use the handles to control which string applies to which plotted object.
Example:
h1 = plot(1:5, 1:5, 'r');
hold on
h2 = plot(1:5, 2:6, 'b');
legend([h1 h2],'First red','Second blue')
The answer above also works for R2017a and higher...here is a little bit more general example:
x = 1:10;
y1 = x;
y2 = 2*x;
y3 = 3*x;
y4 = x.^2;
figure
plot(x, y1, x, y2, x, y3, x, y4);
lh = legend('y = x', 'y = 2*x', 'y = 3*x', 'y = x.^2');
legendEntries = get(gca,'legend')
plotHandles = get(gca,'children')
legendEntries = legendEntries.String;
newOrder = [3,4,1,2];
legend([plotHandles(newOrder)],legendEntries{newOrder})
flipud(h) or fliplr(h) to change complete order of the array up-down oder left-right
Through try and error I found this easy fix:
1) select the plot line that should be at position 1 (at the top)
2) Strg + X
3) Strg + V in the same plot figure
Repeat step 2 and 3 about 3 or 4 time. This will result in the plot beeing at the bottom of the legend. Now select the plot that should be at the 2nd position, again Step 2 and 3 a couple times. The previous plot moves one place up, the 2nd picked plot is now at the bottom.... continue with the rest of the plots the same way