6
$\begingroup$

BarChart is aggravating. Why don't the following correctly display both percentages and labels?

(1)

BarChart[{{1,2,3}},
  ChartLayout -> "Stacked", 
  ChartLabels -> 
    {Placed[{"17%", "33%", "50%"}, Center, Style[#, FontFamily -> "Helvetica", 11]&],
     Placed[{"aa", "bbb", "cccc"}, After, Style[#, FontFamily -> "Helvetica", 14]&]},
  AspectRatio -> 2,
  ImageSize -> 100]

The text labels are rendered correctly (based on an A to a similar Q by Pinguin Dirk here, turns out that the After option left-justifies the text, while numerical parameters don't, even with TextAlignment -> Left set in Style):

chart with incorrect label display

I have also tried using LabelingFunction:

(2)

BarChart[{{1, 2, 3}}, ChartLayout -> "Stacked",
 ChartLabels -> 
  Placed[{"aa", "bbb", "cccc"}, After, 
   Style[#, FontFamily -> "Helvetica", 14] &],
 LabelingFunction -> Placed[{"17%", "33%", "50%"}, Center],
 AspectRatio -> 2, ImageSize -> 100]

But it doesn't display any numbers:

the labels don't work here, either

Finally, this works:

(3)

BarChart[{{1, 2, 3}}, ChartLayout -> "Stacked", ChartLabels -> {
   Placed[{Style[#, FontFamily -> "Helvetica", 10] & /@ {"17%", "33%",
        "50%"},
     Style[#, FontFamily -> "Helvetica", 14] & /@ {"aa", "bbb", 
       "cccc"}}, {Center, After}]},
 AspectRatio -> 2, ImageSize -> 100]

finally, a proper chart!

Is the syntax in (1) and (2) incorrect, or are those bugs?

Also note that FontSize doesn't match. If it is set to the same value for both numerical and text labels, the numerical values look larger. What's going on there?

$\endgroup$

2 Answers 2

6
$\begingroup$

some thoughts, I hope this is what you are after:

ad (1):

It seems (I couldn't find it in the docs) that when you provide a 2-element List of ChartLabels, the first element in a stacked BarChart is treated as a label for a (stacked) bar, the second one is then the intra-bar-label, so to speak. You can view this here:

BarChart[{{1, 2, 3}, {3, 2, 1}, {1, 3, 2}}, ChartLayout -> "Stacked", 
   ChartLabels -> {Placed[{"17%", "33%", "50%"}, Center, 
   Style[#, FontFamily -> "Helvetica", 11] &], 
   Placed[{"aa", "bbb", "cccc"}, After, 
   Style[#, FontFamily -> "Helvetica", 14] &]}, AspectRatio -> 2, 
   ImageSize -> 150]

enter image description here

You can see that the percentages are now labeling the stacked bars. Not what you want.

If you only provide one set of Placed labels, these will be positioned within the bars (what we want). Thus, to get the desired result, we have to provide a 1-element (nested) List. To get it working, we have to make sure we provide the "Position" (Center, After,...) also as a List, so that Mathematica knows how to treat the nested ChartLables, exactly as you did in version (3).

BarChart[{{1, 2, 3}}, ChartLayout -> "Stacked", 
   ChartLabels -> {Placed[{{"17%", "33%", "50%"}, {"aa", "bbb", 
   "cccc"}}, {Center, After}, 
   Style[#, FontFamily -> "Helvetica", 11] &]}, AspectRatio -> 2, 
   ImageSize -> 100]

enter image description here

I think this is about as clean as it can get and the FontSize looks ok to me.

ad (2):

If you wanted to use LabelingFunction, you have to provide a function.

A classical way would be:

LabelingFunction -> (Placed[#1, Center] &)

(parantheses are important!)

Now it seems that this is a bit tricky to get percentages, as you only have access to the individual labels. One could do something ugly such as:

LabelingFunction -> (Placed[{"17%,", "33%", "50%"}[[#2[[2]]]], Center] &)

Add-on

Now the problem I had when looking at that: using ChartLabels one is rather limited, e.g. when plotting several stacked bars. On the other hand, when using LabelingFunction one can directly access individual labels, but the totals are harder to get. Hence the following extension is - I hope - helpful:

With[{tot = Total /@ #}, 
    BarChart[#, ChartLayout -> "Stacked", 
       ChartLabels -> Placed[{"aa", "bbb", "cccc"}, After, 
       Style[#, FontFamily -> "Helvetica", 11] &],
       LabelingFunction -> (Placed[Round[100 #1/tot[[#2[[1]]]]], Center] &),
       AspectRatio -> 1, ImageSize -> 200]] &@{{1, 2, 3}, {3, 3, 3}}

enter image description here

I leave the formatting to you

$\endgroup$
2
$\begingroup$

BarChart is tricky...

If you're working with ChartLayout->"Stacked" it's better, in my opinion, to put labels and percentages in a Grid (or Column) format, because occasionally one might need to show overlapping elements. In this case it would be better to adjust you BarChart using BarSpacing and, maybe, Opacity.

However, the trickiest part is really the LabelingFunction... Let me show what I've done:

Manipulate[
BarChart[{{Ax, Ay, Az}, {Bx, By, Bz}},
TotA := Ax + Ay + Az;
TotB := Bx + By + Bz;
ChartLayout -> "Stacked",
ColorFunction -> u,
BarSpacing -> {0, v},
AspectRatio -> 2,
ImageSize -> 200,
ChartStyle -> Opacity[w],
ChartLabels -> {Placed[{"A", "B"}, Axis], 
Placed[{"x", "y", "z"}, Axis]},
LabelingFunction -> (Placed[
  Grid[{{Style[#3[[2, 1]], Bold, 16, Blue]}, {If[#3[[1, 1]] == "A", 
   Style[N[#1*100/TotA, 3] "%", Red], 
   Style[N[#1*100/TotB, 3] "%", Red]]}}], Center] &)
],
{{Ax, 2, "Ax-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Ay, 5, "Ay-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Az, 4, "Az-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Bx, 6, "Bx-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{By, 3, "By-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Bz, 7, "Bz-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{v, .5, "BarSpacing"}, -1, 2, .1, Appearance -> "Labeled"},
{{w, .5, "Opacity"}, 0, 1, .1, Appearance -> "Labeled"}, 
Button["New Random Color", u = RandomChoice[ColorData["Gradients"]]]]

Result:

enter image description here

Now the same LabelingFunction, this time for three bars.

Manipulate[
BarChart[{{Ax, Ay, Az}, {Bx, By, Bz}, {Cx, Cy, Cz}},
 TotA := Ax + Ay + Az;
 TotB := Bx + By + Bz;
 TotC := Cx + Cy + Cz;
 ChartLayout -> "Stacked",
 ColorFunction -> u,
 BarSpacing -> {0, v},
 AspectRatio -> r,
 ImageSize -> s,
 ChartStyle -> Opacity[w],
 ChartElementFunction -> "ObliqueRectangle",
 ChartLabels -> {Placed[{"A", "B", "C"}, Axis], 
 Placed[{"x", "y", "z"}, Axis]},
 LabelingFunction -> (
 Placed[Grid[{{Style[#3[[2, 1]], Bold, 16, Blue]}, {
     If[#3[[1, 1]] == "A", Style[N[#1*100/TotA, 3] "%", Red], 
      If[#3[[1, 1]] == "B", Style[N[#1*100/TotB, 3] "%", Red], 
       Style[N[#1*100/TotC, 3] "%", Red]]]}}], Center] &)
 ],
{{Ax, 2, "Ax-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Ay, 5, "Ay-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Az, 4, "Az-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Bx, 6, "Bx-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{By, 3, "By-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Bz, 7, "Bz-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Cx, 6, "Cx-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Cy, 3, "Cy-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{Cz, 7, "Cz-value"}, 1, 10, 1, Appearance -> "Labeled"},
{{v, .5, "BarSpacing"}, -1, 2, .1, Appearance -> "Labeled"},
{{w, .5, "Opacity"}, 0, 1, .1, Appearance -> "Labeled"},
{{s, 200, "ImageSize"}, 200, 500, .1, Appearance -> "Labeled"},
{{r, 2, "AspectRatio"}, .5, 3, .1, Appearance -> "Labeled"},
Button["New Random Color", u = RandomChoice[ColorData["Gradients"]]]]

Result:

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.