Data labels above bars on grouped bar plot
152 views (last 30 days)
Show older comments
I'm making a grouped bar plot (i.e., a bar plot with multiple bars in each category). I would like to add labels at the top of each bar to indicate its height. I was planning to just use the text function. However, bars within a given group all have the same x location (i.e get(h,'XData') is the same for all bar series). I'm not sure how to find the proper x location for each bar within a given group. Any ideas?
Thanks, Justin
3 Comments
Benjamin Kraus
on 1 Nov 2024 at 0:09
At long last, bar labels are now built-in to MATLAB as of R2024b.
Check out the new example on the bar doc page: Create Bar Labels and the properties on the Bar object's property page.
Accepted Answer
dpb
on 16 May 2014
Edited: dpb
on 16 May 2014
You're on the right track, the center of each group is at the axis tick value. For each bar in the group, use that value plus/minus a delta to locate the x position for your text.
I did an example of this for another poster within the last few weeks at most altho I don't have the link at hand. Perhaps a search will uncover it.
ADDENDUM:
OK, I looked at past answers--this one is pretty close altho I thought I did another. Maybe it was in the newsgroup instead...
6 Comments
Mostafa Darvishi
on 3 Oct 2016
Hello, I just tumbled into this post and I found it very interesting in my application. in this tripple bar plot, you used the array of [4 3] that means 4 intervals with 3 bars in each interval. But the function that you have used is a random number generator. My question is that how should I change the code in the case that I have 3 arrays as functions. For example I have three following arrays and I want to plot them in triple plot.
Y1 = [1 3 6 7 9 12 11]; Y2 = [12 5 8 13 11 1 4]; Y3 = [11 31 16 17 7 113 15];
dpb
on 3 Oct 2016
Just past 'em together...
Y=[Y1;Y2;Y3].'; % create nx3 column array for *bar*
NB: The latest release of bar uses HG2 and returns a handle to a barobject, rather than the former bar series objects. This new object is essentially opaque to the the details and the data for the patches used to draw the bars isn't available from which to compute the individual bar positions so labelling bars as this example does won't work. I've not got a more recent version so not sure what the workaround is, if there is one or if one must resort back to the earlier "trick" I illustrated before.
More Answers (6)
Benjamin Kraus
on 1 Nov 2024 at 0:22
With the release of MATLAB R2024b, this has gotten much easier.
Starting in MATLAB R2024b, Bar objects now have a Labels property that can be used to add labels to the tops of your bars. You can read about the new properties on the Bar objects property page.
For example:
b = bar(magic(3));
b(1).Labels = ["a","b","c"];
b(2).Labels = ["d","e","f"];
b(3).Labels = ["g","h","i"];
Solution for MATLAB R2019b through R2024a
If you can't upgrade to MATLAB R2024b just yet, you can still do this with a bit more work by using XEndPoints and YEndPoints properties that were added in R2019b.
b = bar(magic(3));
text([b.XEndPoints], [b.YEndPoints], ["a","b","c","d","e","f","g","h","i"], ...
VerticalAlignment='bottom', HorizontalAlignment='center')
9 Comments
Steven Lord
on 2 Nov 2024 at 15:23
I suppose trying having 'left', 'right' when is horizontal instead of 'top','bottom' when vertical would also add excessive cumbersomness to the UI, too, granted...although that would be the way to express.
Funny that you ordered them that way. I caught myself doing that as well when typing a first draft of that comment. Most of the time (when the data was positive) the 'left' label position for a horizontal bar would be the equivalent of the 'bottom' label position for a vertical bar rather than 'top'.
Naming things in a software design often can be easy in one (admittedly probably the most common) case for the designed functionality, but one of the challenges of designing/naming things (functions/methods, classes, properties, etc.) is to make the designs/names understandable, discoverable, and more-or-less accurate (or at least not misleading) in the general case. If I asked you to guess what percentage of the time I've spent in design reviews in have been spent arguing over and/or brainstorming names to generalize them, make them discoverable, and to help users be able to understand their purpose successfully, I'm almost certain you'd guess low.
And sometimes we can't really agree: we spent a lot of time brainstorming other names for Binary Single eXpansion FUNction aka bsxfun.
dpb
on 2 Nov 2024 at 15:52
Edited: dpb
on 2 Nov 2024 at 17:48
I really didn't intend that left,right match top,bottom in the orderwhen posting that, I was just listing the alternative names that were the directional equivalents when horizontal instead of vertical. But, you are correct in that with "normal" positive values and increasing axis values to the right, the baseline would be 'left', and the magnigude to the 'right', instead. As you note, when one gets away from the plain vanilla, it does get complicated to define all the cases unambiguously in a manner that is consistent across all possibilities.
While it's not important to go into reasons why here, I was surprised by the comment that finding the center or other fractional height position so that an arbitrary (percentage say) position along the bar length turned out to be difficult to implement. Then again, I haven't thought in serious depth, so there's probably something obvious I'm overlooking there.
Oh, I can imagine indeed, that is is a very high fraction, indeed, as compared to the base functionality.
As for things like bsxfun, at least it didn't end up with a camel-cased 20-character long moniker! :)
ADDENDUM: Would 'base' and 'head' be orientation agnostic names, maybe???
Will Adler
on 18 Nov 2014
The available bar series properties no longer have the info for the location of the bar. Any idea how to recreate this in grouped bar plots?
8 Comments
dpb
on 21 Sep 2016
What's the issue, specifically? The x-position for the text object to write is given by the above; simply modify the y-position to place where wanted in the bar instead above it--the y distances are computable directly from the data; don't need similar machinations as do for x.
I was thinking I'd seen additional properties mentioned that were useful having been introduced in HG2 but a search the other day didn't seem to find such, unfortunately, so guess I had mixed up with something else.
Kelly Kearney
on 21 Sep 2016
Moving the labels inside the bars is a simple matter of changing the horizontal alignment so the right edge, rather than left, aligns with the bar height (and in most cases, adding a small offset to the y-position so the text doesn't sit flush to the bar edge).
This example also assumes that your bars are all large enough to fit the full text string.
Y=random('unif',30,100,[4 3]); % sample data
h=bar(Y);
yb = cat(1, h.YData);
xb = bsxfun(@plus, h(1).XData, [h.XOffset]');
hold on;
padval = 1;
htxt = text(xb(:),yb(:)-padval, cellstr(num2str(yb(:))), ...
'rotation', 90, 'horiz', 'right');
set(htxt(1:3:end), 'color', 'w'); % for legibility
aliyar attaran
on 4 Nov 2016
for 2 bars one one y value:
for i2=1:numel(y)
tx(i2,1)=text(x(i2),y(i2,1),num2str(y(i2,1),'%0.2f'),...
'HorizontalAlignment','right',...
'VerticalAlignment','bottom');
tx(i2,2)=text(x(i2),y(i2,2),num2str(y(i2,2),'%0.2f'),...
'HorizontalAlignment','left',...
'VerticalAlignment','bottom');
end
0 Comments
Elimelech Schreiber
on 5 Nov 2017
simply:
bar(x);
barvalues;
3 Comments
dpb
on 6 Nov 2017
Edited: dpb
on 6 Nov 2017
I munged on your function some...haven't tested it thoroughly but it now works for the above case...haven't tried for more exotic examples. I know it won't work correctly for 'stacked' as the YData property isn't correct y location for it--not sure if it is retrievable or must be recomputed.
Modifications include
- fixing up isaType to look at all objects in handle array rather than just one (this may be too simplistic in some cases, I don't know; didn't study the search logic enough to know if could possibly pass a group that might be other than bar handles)
- using only one of the array handles in axes call to get axes handle (this could also possibly(?) be too simplistic if there are multiple bar objects but in multiple axes on a given figure), and
- looping over the handle array and adding the .XOffSet property differential to the text call.
Doesn't seem an easy way to add updates at the Exchange so I'll just paste the modified routine here for your convenience...
Giuseppe Naselli
on 15 Jul 2022
Thanks for the barvalues function Elimelech, very easy to use and solid
Very appreciated
G
Halina H
on 7 Dec 2017
Hi , I would like to know how to code to get the total value of each bar in this grouped bar graph ie , total bincounts for the yellow bar, total bincounts for blue bar , and total bincounts for green bar. I am interested to know which of these 3 bars give the most information
1 Comment
Image Analyst
on 15 Jul 2022
Since you plotted the 3 sets of data, you already have the counts. If you want the total number of counts, that's simply the number of elements in the data that you took the histogram of.
See Also
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!