shamalaia
shamalaia

Reputation: 2347

make bar plot with multiple y axis

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?

Upvotes: 3

Views: 1649

Answers (1)

Dan
Dan

Reputation: 45752

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}));

enter image description here

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

enter image description here


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'));

enter image description here

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.

Upvotes: 4

Related Questions