How to add error bars on bar graph with groups?

20 views (last 30 days)
Hi all,
I'm trying to create a bar graph with error bars.
So far, my code is:
c = categorical({'CH','VC','GC','OC','BC','SC'});
c = reordercats(c,{'CH','VC','GC','OC','BC','SC'});
y = [707, 599; 464 444; 522 475; 566 346; 1329 1384; 459 498];
std_dev = [321 271; 233 91; 202 132; 0 173; 410 850; 179 122];
title('Title'); xlabel('x-label'); ylabel('y-label');
figure
hold on
bar(c,y)
errorbar(y,std_dev,'.')
The resulting graph is attached. The error bars appear to stack on top of each other, and are between the the two bars in each pair. I'm unsure how to make each error bar match with individual bars.
If it's helpful, the data in y is annual, where the first number (i.e. 707, 464, 522, 566) is Year 1 and the second number (i.e. 599, 444, 475, 346) is Year 2. The groups are further broken down so that the first three groups (c = CH, VC, GC) are one set and the last three (c = OC, BC, SC) are a second set. If possible, I would also like to have the Year 1 and Year 2 be different colors, as well as the two sets. So, for example, 707 = red, 599 = blue, 459 = green, 498 = orange.
Any help getting started is greatly appreciated!
Cheers
  2 Comments
Star Strider
Star Strider on 11 May 2018
What version of MATLAB are you using?
The categorical data type was introduced in R2013b. A significant change in handle graphics was introduced in R2014b.
DrWooo
DrWooo on 13 May 2018
Edited: DrWooo on 13 May 2018
I am using MATLAB R2016a, and have a trial version of 2018a.

Sign in to comment.

Accepted Answer

Timon Viola
Timon Viola on 11 May 2018
Hey there,
I hope this solution covers what you have been looking for.
close all
clear all
clc
y = [707, 599; 464 444; 522 475; 566 346; 1329 1384; 459 498];
std_dev = [321 271; 233 91; 202 132; 0 173; 410 850; 179 122];
num = 6; %number of different subcategories
c = 1:num;
%%Figure
figH = figure;
axes1 = axes;
title('Title'); xlabel('x-label'); ylabel('y-label');
hold on
%%Bar(s)
%You can not color differently the same bar.
for i = 1:num
bar(c(i)-0.15,y(i,1),0.2);
bar(c(i)+0.15,y(i,2),0.2);
end
%%Errorbar
errH1 = errorbar(c-0.15,y(:,1),std_dev(:,1),'.','Color','b');
errH2 = errorbar(c+0.15,y(:,2),std_dev(:,2),'.','Color','r');
errH1.LineWidth = 1.5;
errH2.LineWidth = 1.5;
errH1.Color = [1 0.5 0];
errH2.Color = [1 0.3 1];
%%Set x-ticks
set(axes1,'Xlim',[0.5 5.5]);
set(axes1,'XTick',[1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6],'XTickLabel',...
{'CH',' ','VC',' ','GC',' ','OC',' ','BC',' ','SC'});
end
If you need more details/comments about the code just let me know. Just the two main problems:
  • Your problem is not that simple... e.g.: you plotted only one bar - which means you have only 2 different data s subsets, that is logically means two different colors.Now to color differently the "subsubsets" ('CH','VC' etc.) and even every bar(!) you have to create a bar for every different colors...
  • The other thing is that you can not position freely your objects when you are working with categorical type. To bypass that just create simple vectors as I did.
  7 Comments
210919
210919 on 2 Dec 2020
This code has been really helpful. Thanks!
@Timon Viola, I was wondering: Could you please clarify what do -0.15 and +0.15 mean in the lines where you build the bars? :
bar(c(i)-0.15,y(i,1),0.2);
bar(c(i)+0.15,y(i,2),0.2);
Thank you.
dpb
dpb on 2 Dec 2020
It's the kludge to find the approximate center of the bars x-position.
See my Answer below for the way to do this without relying on such empirical constants...
Although TMW has added another visible property to the bar object, 'XEndPoints' altho not sure just which release it was in first. It is the X-axis position of the bars in each group for each handle that is the value needed at which to plot the errorbar() (or label the bar or whatever at bar center).

Sign in to comment.

More Answers (1)

dpb
dpb on 11 May 2018
Edited: dpb on 13 May 2018
See <Errors on Bar> to retrieve the locations of the various bars' offsets from the nominal group center.
I would urge to add your complaint to the making of such obviously-desired features so difficult in BAR() by submitting enhancement request/support request. As noted, why TMW would hide the necessary properties is beyond ken. Shows extreme lack of forethought at best; in reality the whole interface ought to be redesigned; it's a klutz.
ADDENDUM
Had a few minutes; hmm....I see the XTick values from the barplot object are returned as the categorical values; not useful for errorbar. OK, go at it this way...
hBar=bar(double(c),y); % plot against the underlying value
hAx=gca; % handle to the axes object
hAx.XTickLabel=categories(c); % label by categories
hold on
X=cell2mat(get(hBar,'XData')).'+[hBar.XOffset]; % compute bar locations
hEB=errorbar(X,y,std_dev,'.') % add the errorbar
for i=1:length(hEB) % See Note...
hEB(i).Color=hBar(i).Facecolor;
end
Above yields
NB: There's a syntax to set multiple handles w/o the loop but its complicated enough I can never get it right the first time or two; see the doc for set for details if want to eliminate the loop as a project... :)
set(hEB,{'Color'},get(hBar,'FaceColor'))
I always forget you have to turn the property name into cellstr to do multiple objects...
NB2: The key feature here is the use of the hidden 'XOffset' property to retrieve the actual midpoint of the bars in each group--this code will work correctly irregardless of the number of groups/number per group, the other Answer uses an approximate constant offset that is specific for only six and two and will have to be modified manually. It's also not quite the right value; close, but not what ML uses internally --
>> [hBar.XOffset] % internal offset
ans =
-0.1429 0.1429
>>
NB3: This also automates setting the colors to match precisely.
NB4: Reiterate to beat on TMW for how difficult is to use BAR() and this about the way categorical is treated just makes it worse...
  4 Comments
Kimberly Stevens
Kimberly Stevens on 13 Jan 2020
This was a great solution; I've been looking all over for a solution to this problem, and yours is by far the best. Thank you much!
dpb
dpb on 13 Jan 2020
I would suggest to add your voice via contact link on enhancement need and the overall bar() interface, too. Maybe eventually TMW will finally do something about it.

Sign in to comment.

Categories

Find more on Data Distribution Plots in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!