Search code examples
matlabplotbar-chartvisualizationmatlab-figure

How to make the lower value in bar graph visible?


I am trying to read values from a spreadsheet and plot them via MATLAB. However, when the values of the first dataset get lower, it becomes hidden at the back, as seen for the values 80 and 100 below:

Bar Graph

I am thinking maybe it's because I am plotting two different bar plots on the same points. How can I to bring the shorter bars to the front?

Below is my code:

%{
Data example:    

Arrival_rate   per_A        per_B

30             46.361       44.892
60             30.585       25.602
80             20.674       23.352
100            16.209       18.597
%}

fig = figure('DefaultAxesFontSize',18);
set(0,'DefaultAxesFontName','Times New Roman');

arrival_rate = xlsread('Graph_data', 'Sheet2', 'H1:H6');
pe_a = xlsread('Graph_data', 'Sheet2', 'I1:I6');
pe_b = xlsread('Graph_data', 'Sheet2', 'J1:J6');
line = xlsread('Graph_data', 'Sheet2', 'K1:K6');

x1 = 30:1:100;
y1 = [46.361 44.892; 30.585 25.602; 16.209  18.597];
x2 = 30:1:100;
y2 = interp1(arrival_rate,line,x2,'pchip') ;

hold on 

ylabel('% error in VM_A')

% bar(arrival_rate,y,  0.2, 'b', 'DisplayName', 'Error in A') 
bar(arrival_rate,pe_a ,.1 , 'stacked','DisplayName', 'Error in A') 
bar(arrival_rate,pe_b, .1 , 'stacked', 'DisplayName', 'Error in B')

% bar(arrival_rate, y1, 0.2, 'hist')

plot(x2,y2,'k.','HandleVisibility','off','LineWidth',1) 
plot(arrival_rate,line,'k*', 'HandleVisibility','off','LineWidth',1) 


hold off

xlabel('\lambda (Clients/Hour) ')
ylabel('Error (%)')
%  title('Effect of Probability of a VM Type on awt of Clients')
legend show
legend('Location','Northeast')
set(gca,'XTick',(0:10:110))
set(gca,'YTick',(0:5:50))

set(gcf, 'PaperUnits', 'normalized')
set(gcf, 'PaperOrientation', 'landscape') 
set(gcf, 'PaperPosition', [0 0 1 1])  

Solution

  • From what I understand, for the case where the blue bars are shorted than the red, they should appear in the front. Unfortunately, MATLAB does not make it easy for you to control each bar individually, which should hint that this is not something they intend for to do. (In other words - it would be a good idea to consider other ways of visualizing the data in a meaningful way.)

    I'd suggest you to make the width of the bars slightly different, so that you could easily tell what's going on at a glance:

    D = [...
    30             46.361       44.892
    60             30.585       25.602
    80             20.674       23.352
    100            16.209       18.597];
    
    arrival_rate = D(:,1);
    pe_a = D(:,2);
    pe_b = D(:,3);
    
    fig = figure('DefaultAxesFontSize',18);
    bar(arrival_rate,pe_a ,.15 , 'stacked','DisplayName', 'Error in A'); hold on;
    bar(arrival_rate,pe_b, .1 , 'stacked', 'DisplayName', 'Error in B');
    

    which gives:

    Option 1

    Now, if you insist on having it your way, I can think of asolution, but it would be increasingly difficult to extend to more than 2 groups. In short you make plots in this order and then they'll appear correctly:

    1. Blue (optionally: only where blue is taller).
    2. Red.
    3. Blue over red (when red is taller).

    fig = figure('DefaultAxesFontSize',18);
    
    bar(arrival_rate,pe_a, .1 , 'DisplayName', 'Error in A'); hold on;
    bar(arrival_rate,pe_b, .1 , 'DisplayName', 'Error in B');
    bar(arrival_rate(is_blue_smaller), pe_a(is_blue_smaller), .1 , ...
      'FaceColor', lines(1), 'HandleVisibility','off');
    

    which yields:

    Option 2