A custom DisplayFunction
that adds legends and data table with columns aligned with group labels:
ClearAll[displayF]
displayF[lgnds_, tbl_, lbgrnd_: Automatic, tbgrnd_: Automatic, voffset_: 25, gap_:25] :=
Module[{volist = Accumulate[Prepend[gap] @ ConstantArray[voffset, Length @ tbl]],
hoffset = 1.1 Max[Ceiling[Rasterize[Style[#, "Graphics"],
"RasterSize"], 10][[1]] & /@ lgnds],
hcoords = Map[MinMax @* Flatten] @
Partition[Cases[#[[1]], (RectangleBox | Rectangle)[a_, b_, ___] :>
{First @ a, First @ b}, All], Length[tbl]],
legendalign = ("MarkerLayout" /. Options[First@lgnds]) /. {"After" -> 1, _ -> -1},
hrange, offsets, texts, tablelegend, ma},
hrange = MinMax @ hcoords;
ma = MovingAverage[volist, 2];
offsets = Outer[Offset, Thread[{0, -ma}], Thread[{Mean /@ hcoords, 0}], 1];
texts = Join @@ MapThread[Text[##, {0, 0}] &, {tbl, offsets}, 2];
tablelegend = {lbgrnd /. Automatic -> Lighter[Gray, .5],
Rectangle @@ MapThread[Offset[{-#, -#2}, {hrange[[1]], 0}] &,
{{hoffset, 0}, volist[[{1, -1}]]}],
tbgrnd /. Automatic -> Lighter[Gray, .8],
Rectangle @@ MapThread[Offset[{0, -#}, {#2, 0}] &, {volist[[{1, -1}]], hrange}],
CapForm["Round"], Thick, Darker @ Red,
Table[Line[{Offset[{-hoffset, -i}, {hrange[[1]], 0}],
Offset[{0, -i}, {hrange[[2]], 0}]}], {i, volist}],
Black, texts,
MapThread[Inset[#, Offset[{- hoffset Boole[legendalign < 0], -#2},
{hrange[[1]], 0}], {legendalign, Center}] &, {lgnds, ma}]};
Show[#, Graphics @ tablelegend, PlotRange -> All]] &
Examples:
air = {3, 1, 6}; water = {2, 4, 3}; road = {1, 0, 7}; root = {6, 1, 2};
data = {air, water, road, root};
clist = {"Belarus", "Georgia", "Armenia"};
legendlabels = {"change in air", "flowing water", "construction road",
"agriculture root"};
colors = ColorData["Rainbow"] /@ Rescale@Range[Length @ data];
legends = MapThread[
SwatchLegend[{#}, {#2}, LegendLayout -> "Column", "MarkerLayout" -> "After"] &,
{colors, StringPadLeft[legendlabels]}];
BarChart[Transpose @ data,
ChartLabels -> {Placed[clist, Below], None},
ChartStyle -> {None, "Rainbow"},
FrameLabel -> {{"PercentChange", None}, {None, None}},
PlotTheme -> "Business",
AspectRatio -> 2/3,
ImageSize -> 600,
DisplayFunction -> displayF[legends, data]]
Let
legends2 = MapThread[SwatchLegend[{#}, {#2}, LegendLayout -> "Column"] &,
{colors, legendlabels}];
and use DisplayFunction -> displayF[legends2, data]
to get:
Use
DisplayFunction ->
displayF[Append[{LegendMarkerSize -> 20, LegendMarkers -> "Bubble",
LabelStyle -> {White, 24}}] /@ legends,
Map[Map[Style[#, 24, White] &]] @ data, Black, Gray, 40]
to get
SeedRandom[1]
randomdata = RandomInteger[100, {5, 6}];
labels = RandomWord["Noun", 6];
legendLabels = Style[#, 14] & /@ Table[StringRiffle[RandomWord["Noun", 3]], 5];
swatchlegends = MapThread[
SwatchLegend[{#}, {#2}, LegendLayout -> "Column", "MarkerLayout" -> "After"] &,
{ColorData["Pastel"] /@ Rescale[Range @ 5], legendLabels}];
BarChart[Transpose @ randomdata,
ChartLabels -> {Placed[labels, Below], None},
ChartStyle -> {None, "Pastel"},
FrameLabel -> {{"PercentChange", None}, {None, None}},
PlotTheme -> "Business", AspectRatio -> 2/3, ImageSize -> 800,
DisplayFunction -> displayF[swatchlegends,
Map[Style[#, 14, White] &] /@ randomdata, Automatic, Black]]
twogroups = randomdata[[All, ;; 2]];
twolabels = labels[[;; 2]];
BarChart[Transpose @ twogroups ,
ChartLabels -> {Placed[twolabels, Below], None},
ChartStyle -> {None, "Pastel"},
BarSpacing -> {.25, 2},
FrameLabel -> {{"PercentChange", None}, {None, None}},
PlotTheme -> "Business", AspectRatio -> 2/3, ImageSize -> 800,
DisplayFunction -> displayF[swatchlegends,
Map[Style[#, 14, White] &] /@ twogroups, Automatic, Black]]