OK for example the numeric value of one of my data is large and the numeric value of one of my data is small.
A = [130000 310000 200000 400000]';
B = [16 32 5 10]';
I am doing the following.
figure;
bar(1:4,[A B],0.5,'stack');
Since the value of A is lot high than B, I want a secondary y-axis. Otherwise the values of B cannot be seen on the stacked bar chart.
You can use plotyy to plot two bar charts on different y-axes in the same figure.
x = [1,2,3];
y1 = [1000,2000,3000];
y2 = [0.5,0.3,0.1];
[AX,H1,H2] = plotyy(x, y1, x, y2, 'bar', 'bar');
set(H1, 'FaceColor', [1 0 0], 'BarWidth', 1)
This isn't a stacked bar chart like you had before (one set of data vertically on top of the other) but it doesn't make sense include data on different scales in a stacked bar chart.
Related
I am trying to plot a bar graph with means of 9 data points. I want to plot the bar graph with individual data points overlaid on the bar. Here is the code to generate the bar graph. I want to overlay each bar with the individual data points whose average is y. Any suggestions for how to do this would be helpful. Thank you!
x_num = [1:4];
x = categorical({'High PU-High RU','High PU-Low RU', 'Low PU-High RU', 'Low PU-Low RU'});
y = [0.557954545, 0.671394799, 0.543181818, 0.660227273];
figure
bar(x,y,0.4)
title('Economic Performance')
xlabel('Conditions')
You can just hold on and plot the additional points
% Generate some data
x = 1:4;
y = rand(9,4); % note: 4 columns, N rows
ymean = mean(y); % mean of each column for bar
figure();
hold on; % plot multiple things without clearing the axes
bar( x, ymean, 0.4 ); % bar of the means
plot( x, y, 'ok' ); % scatter of the data. 'o' for marker, 'k' for black
hold off
There are loads of options for the plot styling, using 'o', 'x' or '.' as a marker type will make it a scatter rather than a line which is what you want here, other than that you can go crazy with sizing/color/linewidth etc, see the documentation.
I have a matrix, A, that contains 50 rows and 4 columns, and the entries are filled with integers. My interest is to construct a stacked 3D bar plot from this data. However, using bar3(A,'stacked') creates a row of 50 bars, whereas I want the bars to be plotted at the coordinates of a grid of size 5 (vertical) x 10 (horizontal). So the first bar in the row would be at location (1,1), second bar at (1,2), 11th bar at (2,1) and so on until the 50th bar which would be at (5,10). I can't seem to find a way to do this in Matlab, is this possible at all?
Thank you in advance!
I agree with #cris, there are better ways to represent your data. However, something like this would work if you still want to do use a 3D bar plot:
figure
hold on
for i = 1:5
Ai = A(10*(i-1)+1:10*i,:);
h = bar3(1:10,Ai,'stacked');
for ih = 1 :length(h)
x = get(h(ih), 'Xdata');
set(h(ih), 'Xdata', x+i-1);
end
end
view(3)
I have a tricky question, which I think cannot be simply answered.
I have a large data table and want to save bar charts for each 2 corresponding mean values. I already did that with "for loop", but I cannot set different colors to my bars and cannot set proper spaces between bars and axes.
That's the simplest example:
k = [2 5]
bar(k)
Matlab thinks about those data [2 5] as about one "group" and it does not give a possibility of changing color for only one bar.
Of course, when we have different "groups", colors are changeable.
y = bar([1 2 3; 4 5 6]);
y(2).FaceColor = 'red';
But what about my example? I need only two bars, and I need to color them differently. Also, I want to set a small space between each bar and the axes (and again with two bars it is not that simple, and I cannot use "bar width" because that doesn't give me what I really want).
Does anyone know how to get around this?
Thanks for any reply!
Mary
A good trick could be add zero column for each group:
k = [2 5;0 0];
bar(k,'grouped')
UPDATE
Another solution to have different color could be using location in bar:
k = [2 5];
figure(1);
hold on;
h=bar(1,k(1));
set(h,'FaceColor','k');
h=bar(2,k(2));
set(h,'FaceColor','b');
hold off
As far as I know, this requires the use of a custom bar plot, since Matlab's barplots use dynamic colormaps. Personally, I like the GRAMM toolbox for all these customizations: [GRAMM on file-exchange] [GRAMM on github].
Here's an example:
x = [1 2];
y = [1 1.5];
c = x;
custom_map = ...
[1 0.3673 0.4132;
0 0.7375 0.8344];
clear g
g(1,1)=gramm('x',x,'y',y,'color',c);
g(1,1).geom_bar('width',0.2);
g(1,1).set_title('Width = 0.2');
g(1,2)=gramm('x',x,'y',y,'color',c);
g(1,2).geom_bar('width',0.8);
g(1,2).set_title('Width = 0.8');
g.set_names('y','','x','');
g.set_color_options('map',custom_map);
g.axe_property('YTick',[],'LineWidth',1,'YColor',[1 1 1],'XLim',[0.5 2.5],'XTick',[1 2])
figure('Position',[100 100 600 300]);
g.draw();
The histogram function is one option that will easily handle the spacing and x-axis labeling, but you'll have to plot each bar separately to independently control the colors:
k = [2 5];
histogram('Categories', {'ONE'}, 'BinCounts', k(1), 'BarWidth', 0.8, ...
'FaceAlpha', 1, 'FaceColor', [0 0.4470 0.7410]);
hold on;
histogram('Categories', {'TWO'}, 'BinCounts', k(2), 'BarWidth', 0.8, ...
'FaceAlpha', 1, 'FaceColor', [0.8500 0.3250 0.0980]);
Here is an option to workaround this. You can use diag(k) to create a 2*2 matrix with all zeros except the main diagonal that will be with your values, and Matlab will read it as 2 different groups. Then you change the Xdata of the 'dummy' bars (which you don't see but take some space on the x axis to nan so Matlab will ignore it.
k = [2 5];
b = bar(diag(k));
set(b,{'XData'},{[1 nan],[nan 1]}); % remove the group you don't want
set(gca,{'xticklabel','XTick'},{{'ONE','TWO'},[0.85 1.15]});
b(2).FaceColor = 'r'; % choose a different color
The result:
And if you want to generalize this to more groups (here it's 5):
k = 1:5;
data = diag(k);
xdata = eye(numel(k))./eye(numel(k)); % a martix of nan with 1 on the main diagonal
b = bar(diag(k));
% remove all data except one bin in all groups:
set(b,{'XData'},mat2cell(xdata,ones(size(data,1),1),size(data,2)))
X = xlim; 5 get x-axis limits
w = (1-X(1))/(numel(k)/2); % calculate the width of one bin
set(gca,'XTick',X(1)+w/2:w:X(2)) % set the X ticks to the center of the bins
set(gca,'xticklabel',{'ONE','TWO','THREE','FOUR','FIVE'}); % set the labels
set(b,{'FaceColor'},mat2cell(lines(numel(k)),ones(size(data,1),1),3)); % set the colors
and you get:
And finally, if you want them to 'hover' a little above the x-axis, you can add the following lines:
b(1).BaseLine.Color = 'none'; % remove the base line
ylim([-0.1 max(k(:))]) % shift the bars up a little
and get:
I have some data I want to represent with a bar graph:
AAA=[2/3 1.5/3 .5/3 3; 1.5/3 1.8/3 .5/3 2.8];
figure
bar([1 2], AAA, 'BarWidth', 1)
But I would like to use one y-axis for the first three bars of each line of AAA and a different one for the fourth.
I could't use plotyy as suggested here because I have too many entries.
Do you know some alternatives?
WARNING: This solution does not generalize easily when you have different numbers of bars... a different method that generalized a bit better is presented at the end
From reading the docs, I don't see why plotyy wouldn't work (aside from being deprecated in favour of yyaxis in 2016a).
plotyy(X1,Y1,X2,Y2,'function1','function2') uses function1(X1,Y1) to plot the data for the left axis and function2(X2,Y2) to plot the data for the right axis.
y1 = [2/3 1.5/3 .5/3; 1.5/3 1.8/3 .5/3];
y2 = [3; 2.8];
x = [1,2];
figure
% based on http://stackoverflow.com/questions/18688381/matlab-bar-plot-grouped-but-in-different-y-scales
offset = (x(2)-x(1))/16; %needs to be generalised, so the 16 should be something like 2^(size(y1,2)+1) or 2^(size(y1,2)+size(y2,2))
width = (x(2)-x(1))/4; %The 4 here also needs to be generalized
colors = {'b','g'};
plotyy(x-offset*5,y1,x+offset*2,y2, #(x,y) bar(x,y,width*4,colors{1}), #(x,y) bar(x,y,width,colors{2}));
But I would question whether or not it would be clearer to rather just use subplot
If you want to change the colours of the individual bars (per category that is), you have to do it manually:
h = plotyy(x-offset*5,y1,x+offset*2,y2, #(x,y) bar(x,y,width*4,colors{1}), #(x,y) bar(x,y,width,colors{2}));
barGroup1 = h(1).Children;
map1 = [0, 0, 0.4;
0, 0, 0.6;
0, 0, 1];
for b = 1:numel(barGroup1)
barGroup1(b).FaceColor = map1(b,:);
end
Another way to do this is instead of messing around with offset and width variables, just pad each y with a bunch of 0s:
y1 = [2/3 1.5/3 .5/3,1; 1.5/3 1.8/3 .5/3,1;1,1,1,1];
y2 = [3,1; 2.8,1;1,1];
x = [1,2,4]; %x doesn't need to go up in increments of 1 (spacing will differ as you can see in the image), however it can only contain integers
nCol = max(size(y1,2),size(y2,2))*2;
Y1 = zeros(size(y1,1),nCol);
Y2 = zeros(size(y2,1),nCol);
% The idea is the make all the bars from group 1 sit before the group number (i.e. the numbers going from the halfway mark backwards) and all the bars from group 2 sit after the halfway mark (i.e. the numbers from the middle(+1) going forward)
Y1(:,nCol/2-size(y1,2)+1:nCol/2) = y1
Y2(:,nCol/2+1:nCol/2+1+size(y2,2)-1) = y2
h = plotyy(x,Y1,x,Y2, #(x,y) bar(x,y,1,'b'), #(x,y) bar(x,y,1,'g'));
You can colour this chart the same way as above. This should generalize no matter the number of bars. Unfortunately you can't control the size of the gap between the groups.
I have the following data sets to plot:
data1 = [ 3 6 99 4 5];
data2 = [ 0.2 1.5 1.75 1.0 1.2];
What's peculiar about my situation is that I need data point data1(3), which is equal to 99, not show up on the graph. I'm using 99 as a way of pushing observations outside the desired axis limits so that there are no visible observations for certain values of the independent variable. (I'm plotting the data points with markers only, no lines.)
While data1 and data2 have totally unrelated scales and meanings, they share the exact same dependent variable:
X=40:1:44
I'm plotting with the following commands, which I derived from the MATLAB plotyy documentation page:
[AX,H1,H2] = plotyy(X,data1,X,data2);
set(get(AX(1),'Ylabel'),'String','This is vertical axis 1')
set(get(AX(2),'Ylabel'),'String','This is vertical axis 2')
set(H1,'LineStyle','none','Marker','*');
set(H2,'LineStyle','none','Marker','s');
So far, so good. What I cannot figure out is how to enforce the correct limits on both of the vertical axes. My desired limits are:
ylimits1=[0 3]
ylimits2=[0 10]
How can I set limits for each vertical axis?
I have tried this
set(get(AX(1),'Ylim'),ylimits1)
set(get(AX(2),'Ylim'),ylimits2)
and
foo = gca
set(foo(1),'ylim',ylimits1);
set(foo(2),'ylim',ylimits2);
but neither work.
the following should work:
[AX,H1,H2] = plotyy(X,data1,X,data2);
set(AX(1),'ylim',ylimits1);
set(AX(2),'ylim',ylimits2);
some other random things you can do
x1 = 1:10
y1 = x1.^2
x2 = 10:120
y2 = sin(x2)
[AX,~,~] = plotyy(x1,y1,x2,y2);
set(get(AX(1),'Xlabel'),'String','both plots')
set(get(AX(2),'Ylabel'),'String','plot 2')
set(AX(1),'YLim',[1 25],'YTick',7:23)