2

I have the following code for a plot with 2 y-axes in MATLAB. I am glad that the 2-axes feature works, however, I would like to avoid the overlapping of the bars. Also, the categories on the right-hand axis should have different colors, not only yellow, yet it should be somehow clear that they are plotted on the right-hand axis and not the left one. How can this be done?

EONMW = [100 399 500]; RWEMW = [200 996 120]; GermanByEON = [0.2 0.4 0.5]; GermanByRWE = [0.1 0.5 0.9]; EONGermanPortfolio = [0.7 0.2 0.1]; RWEGermanPortfolio = [0.8 0.3 0.6]; years = [2010 2012 2014]; % Plot values1 = [EONMW; RWEMW]'; values2 = [GermanByEON; GermanByRWE; EONGermanPortfolio; RWEGermanPortfolio]'; years1 = [years; years]'; years2 = [years; years; years; years]'; figure; bar(years1,values1); ylabel('Utilities generation portfolio in MW') yyaxis right bar(years2,values2); legend('EON German portfolio in MW', 'RWE German portfolio in MW',... 'Percentage of German portfolio by EON', 'Percentage of German portfolio by RWE',... 'EON"s percentage of generation in Germany', 'RWE"s percentage of generation in Germany') legend('Location','northwest') ylabel('Utilities generation portfolio as percentages') 

enter image description here

4
  • OK, see my edit! Commented Jan 7, 2019 at 9:39
  • 2
    The edit makes the question clearer, but the fact you've got 3 different metrics on a single plot is pretty unclear from a (personal) data visualisation perspective... consider just using subplot instead, you can split your data into stacked plots so they line up on the x axis but the purpose and content of each plot is clearer. It will also save you getting bogged down in workarounds for the above, which I'm not sure will be easy for bar. The reason all yyaxis right bars are the same colour is so you know which axis they lie on - how would you know otherwise? Commented Jan 7, 2019 at 9:59
  • Related from same OP: stackoverflow.com/questions/54071530/… Commented Jan 7, 2019 at 22:36
  • I would not recommend plotting the data like this (even with the suggestion of @Dev-iL). I can't see any advantage in plotting these bar plots with 2 y-axes, instead of using 2 vertical subplots, with aligned years. Why plotting the bars together if they can't be compared anyway? Commented Jan 8, 2019 at 7:02

3 Answers 3

7

I agree that it is somewhat difficult to read this sort of plot, but perhaps there's a way to improve the situation a little.

The main thing I changed was adding invisible bars (using NaN) so that the color order remains intact:

function q54071610 EONMW = [100 399 500]; RWEMW = [200 996 120]; GermanByEON = [0.2 0.4 0.5]; GermanByRWE = [0.1 0.5 0.9]; EONGermanPortfolio = [0.7 0.2 0.1]; RWEGermanPortfolio = [0.8 0.3 0.6]; years = [2010 2012 2014]; % Plot values1 = [[EONMW; RWEMW].' NaN(3,4)]; values2 = [NaN(3,2) [GermanByEON; GermanByRWE; EONGermanPortfolio; RWEGermanPortfolio].']; years1 = repmat(years.', [1,6]); figure; bar(years1,values1, 'EdgeColor', 'b', 'LineWidth', 2); ylabel('Utilities generation portfolio in MW') yyaxis right hB = bar(years1,values2, 'EdgeColor', 'r', 'LineWidth', 2); c = lines(6); for ind1 = 1:6 hB(ind1).FaceColor = c(ind1, :); end legend('EON German portfolio in MW', 'RWE German portfolio in MW',... 'Percentage of German portfolio by EON', 'Percentage of German portfolio by RWE',... 'EON"s percentage of generation in Germany', 'RWE"s percentage of generation in Germany') legend('Location','northwest') ylabel('Utilities generation portfolio as percentages') 

Which results in:

enter image description here

Now you should explain that red-framed bars belong to the right axis whereas blue-framed bars belong to the left.

Sign up to request clarification or add additional context in comments.

2 Comments

This is nice, thank you! Only problem: in the legend the entries show up with only blue frames...
Yes, I noticed this. Not sure what can be done (editing the legend entries should be possible but likely difficult). What you can do is maybe plot another bar plot, in advance, with all NaN y-values and then show the legend (which will have small black frames around entries, as in your image). Just add bar(years1,NaN*values1); hold on; after figure; and see if the result works for you.
1

I'm not sure what exactly these bars mean, and so I may have missed the point of the figure (which could be the main problem here). However, I find this way of presentation not pleasing and misleading, as it takes a lot of effort from the reader to understand which value belongs to which bar, and what is comparable and what's not.

What I suggest here, is not a direct answer to the technical problem (which you have already got from @Dev-iL), but a different solution for the more basic problem - how to visualize these data? I believe that if I'll understand what the numbers represent (percentage from what?) and what you want to emphasize with this plot, I can find a better solution.

First, the code:

EONMW = [100 399 500]; RWEMW = [200 996 120]; GermanByEON = [0.2 0.4 0.5]; GermanByRWE = [0.1 0.5 0.9]; EONGermanPortfolio = [0.7 0.2 0.1]; RWEGermanPortfolio = [0.8 0.3 0.6]; years = [2010 2012 2014].'; values1 = [EONMW; RWEMW].'; values2 = [GermanByEON; GermanByRWE; EONGermanPortfolio; RWEGermanPortfolio].'*100; % Plot colMap = mat2cell(lines(2),[1 1],3); % Choose your favorite colors figure(2); % upper plot: subplot 211 b = bar(years,values1); set(b,{'FaceColor'},colMap) xticklabels({}) % remove the years labels, the bottom axes will show them ylabel('Utilities generation portfolio in MW') legend('EON German', 'RWE German',... 'Location','northwest') % bottom plot subplot 212 b = bar(years,values2); set(b,{'FaceColor'},repmat(colMap,2,1)) % matching the colors by topic set(b,{'FaceAlpha'},{1;1;0.6;0.6}) % distiguish between related mesures xlabel('Year') ylabel('Utilities generation portfolio (%)') legend('German portfolio by EON', 'German portfolio by RWE',... 'EON''s generation in Germany', 'RWE''s generation in Germany',... 'Location','north') 

The result: enter image description here

The major things I changed:

  1. Split the bars by the units of the y-axis, but align them by the x-axis
  2. Match the colors of related bars between the plots
  3. Shorten legends and labels

Good luck!

Comments

0

It is best if you define bar(x,y) as b=bar(x,y) then control the options of b one of such is b.FaceColor. Take a look at the following code

EONMW = [100 399 500]; RWEMW = [200 996 120]; GermanByEON = [0.2 0.4 0.5]; GermanByRWE = [0.1 0.5 0.9]; EONGermanPortfolio = [0.7 0.2 0.1]; RWEGermanPortfolio = [0.8 0.3 0.6]; years = [2010 2012 2014]; x=0.2; % Plot values1 = [EONMW; RWEMW]'; values2 = [GermanByEON; GermanByRWE; EONGermanPortfolio; RWEGermanPortfolio]'; years1 = [years; years]'; years2 = [years; years; years; years]'; figure; b1=bar(years1,values1,x*0.66); ylabel('Utilities generation portfolio in MW') yyaxis right b2=bar(years2,values2,x); %%%%%%%%%%%% %%%%%%%%%%%% %% Defining colors b1(1).FaceColor=[1 0 0]; b1(2).FaceColor=[0 1 0]; b2(1).FaceColor=[0 0 1]; b2(2).FaceColor=[1 1 0]; b2(3).FaceColor=[0 1 1]; b2(4).FaceColor=[1 0 1]; %%%%%%%%%%%% %%%%%%%%%%%% %% legend('EON German portfolio in MW', 'RWE German portfolio in MW',... 'Percentage of German portfolio by EON', 'Percentage of German portfolio by RWE',... 'EON"s percentage of generation in Germany', 'RWE"s percentage of generation in Germany') legend('Location','northwest') ylabel('Utilities generation portfolio as percentages') 

which is your code plus the following block

%%%%%%%%%%%% %%%%%%%%%%%% %% Defining colors b1(1).FaceColor=[1 0 0]; b1(2).FaceColor=[0 1 0]; b2(1).FaceColor=[0 0 1]; b2(2).FaceColor=[1 1 0]; b2(3).FaceColor=[0 1 1]; b2(4).FaceColor=[1 0 1]; %%%%%%%%%%%% %%%%%%%%%%%% %% 

and the result is as follows

enter image description here

also a trigger option x has been added to control bar width.

5 Comments

But how do you now tell which bar belongs to which axis?
In the code above, after defining b=bar(x,y), b becomes a vector each component being the corresponding bar control panel. For example if b=bar(x,y) where x and y are 2*20 vectors, then b maintains a 2*1 vector with b(1) relating to bar(x(1,:),y(1,:)) and b(2) relating to bar(x(2,:),y(2,:))
@mostafa I believe he meant to ask how does the viewer understand if they should read the y value from the left or the right axis?
Do you mean when printed with a black-ink on paper(for which colors become indistinct)? Otherwise, I think the colors and the legend are self explaining....
@MostafaAyaz Even before printing... Since we have two y-axes which mean different things (it's not a matter of just converting units, the meaning of the axes is completely different). Now, each bar should be read according to the correct y-axis, so the question is - how does your suggestion tell the reader if they should look at the right axis or the left axis? I hope it's clear now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.