1
$\begingroup$

This question is nothing more than making a few changes to an already working code. I put that code into Manipulate[...] to be able to choose a subset of countries and a subset of indicators.

By @kglr, the code below creates a perfect chart:

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]] &

And then, I adjusted @kglr's code using Manipulate[ ]

ClearAll[air, water, road, root, data, clist, xlist, colors, legends];

air = {3, 1, 6, 3, 1, 6};
water = {2, 4, 3, 2, 4, 3};
road = {1, 0, 7, 1, 0, 7};
root = {6, 1, 2, 6, 1, 2};

data = {air, water, road, root};
clist = {"Belarus", "USA", "France", "Turkey", "Georgia", "China"};
xlist = {"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[xlist]}];

Manipulate[
 data1 = (#[[;; noC]] & /@ data);
 BarChart[
  Transpose@data1,
  ChartLabels -> {Placed[clist, Below], None},
  ChartStyle -> {None, "Rainbow"},
  FrameLabel -> {{"Percent Change", None}, {None, None}},
  PlotTheme -> "Business",
  AspectRatio -> 2/3,
  ImageSize -> 500,
  DisplayFunction -> displayF[legends, data1]
  ],
 {{noC, 4, "countries"}, Thread[Range[Length[clist]] -> clist], 
  ControlType -> SetterBar},
 {{noV, 2, "indicators"}, Thread[Range[Length[xlist]] -> xlist], 
  ControlType -> SetterBar},
 Paneled -> False
 ]

This produced:

enter image description here

But there are two issues to solve:

  1. When I choose a single country, such as Turkey, the code gives me all the countries listed before Turkey (including Turkey as well). I like to choose a few countries from the list clist;
  2. I also like to choose at will a few indicators from the list xlist.

I tried the following:

Manipulate[
 data1 = {(#[[;; nbrC]] & /@ data)[[nbrV, All]]};
 BarChart[
  Transpose@data1,
  ChartLabels -> {Placed[clist, Below], None},
  ChartStyle -> {None, "Rainbow"},
  FrameLabel -> {{"Percent Change", None}, {None, None}},
  PlotTheme -> "Business",
  AspectRatio -> 2/3,
  ImageSize -> 500,
  DisplayFunction -> displayF[legends, data1]
  ],
 {{nbrC, 4, "countries"}, Thread[Range[Length[clist]] -> clist], 
  ControlType -> SetterBar},
 {{nbrV, 2, "indicators"}, Thread[Range[Length[xlist]] -> xlist], 
  ControlType -> SetterBar},
 Paneled -> False
 ]

enter image description here

This trial is way behind what I hoped to have.

$\endgroup$

1 Answer 1

3
$\begingroup$
Manipulate[With[{data1 = data[[noV, noC]]},
  If[noV == {} || noC == {}, 
   Graphics[{}, Frame -> True, FrameTicks -> False, 
    AspectRatio -> 2/3, ImageSize -> 500], 
   BarChart[Transpose @ data1, 
    ChartLabels -> {Placed[clist[[noC]], Below], None}, 
    ChartStyle -> {None, colors[[noV]]}, 
    FrameLabel -> {{"Percent Change", None}, {None, None}}, 
    PlotTheme -> "Business", AspectRatio -> 2/3, ImageSize -> 500, 
    DisplayFunction -> displayF[legends[[noV]], data1]]]], 
 {{noC, Range[Length[clist]], "countries"}, 
  Thread[Range[Length[clist]] -> clist], TogglerBar, 
  TrackingFunction -> (noC = Sort[#]; &)},
 {{noV, Range[Length[xlist]], "indicators"}, 
  Thread[Range[Length[xlist]] -> xlist], TogglerBar, 
  TrackingFunction -> (noV = Sort[#]; &)}, Paneled -> False]

enter image description here

A variation: replace the second control with

{{noV, Range[Length[xlist]], "indicators"}, 
 Thread[Range[Length[xlist]] -> (Append[#, 
       Background -> Opacity[.3, #[[1, 1]]]] & /@ legends)], 
 TogglerBar, Appearance -> { "Pressed", "Normal"}, 
 TrackingFunction -> (noV = Sort[#]; &)}

to get

enter image description here

$\endgroup$

Your Answer

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

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