3
$\begingroup$

I have the following code which produces an animated bar chart.

counts = 101;
names = Sort[{"name01", "name02", "name03", "name04", "name05"}];
nbars = Length[names];

maxRandomNumber = 1;

data = Array[0 &, {nbars, counts}];

Do[data[[All, i]] = data[[All, i - 1]] + 
 RandomInteger[maxRandomNumber, nbars];, {i, 2, counts}];

Animate[BarChart[data[[All, i + 1]], ImagePadding -> All, 
  Frame -> True, ChartStyle -> "BlueGreenYellow", 
  PlotRange -> {{0, nbars + 1}, {0, 1.1*Max@Flatten@data}}, 
  ImageSize -> 600, 
  ChartLabels -> Placed[names, Axis, Rotate[#, -Pi/2] &], 
  LabelingFunction -> (Placed[Panel[#1, FrameMargins -> 0], Above] &),
   FrameLabel -> {{"votes", ""}, {"names", ""}}, 
  ChartLegends -> names], {i, 0, counts - 1, 1, 
  Appearance -> "Labeled"}, AnimationRepetitions -> 1, 
 DefaultDuration -> 20, AnimationRunning -> False]

enter image description here

Now I want to sort the bars by decreasing number:

Animate[BarChart[Sort[data[[All, i + 1]], Greater], 
  ImagePadding -> All, Frame -> True, ChartStyle -> "BlueGreenYellow",
   PlotRange -> {{0, nbars + 1}, {0, 1.1*Max@Flatten@data}}, 
  ImageSize -> 600, 
  ChartLabels -> Placed[names, Axis, Rotate[#, -Pi/2] &], 
  LabelingFunction -> (Placed[Panel[#1, FrameMargins -> 0], Above] &),
   FrameLabel -> {{"votes", ""}, {"names", ""}}, 
  ChartLegends -> names], {i, 0, counts - 1, 1, 
  Appearance -> "Labeled"}, AnimationRepetitions -> 1, 
 DefaultDuration -> 20, AnimationRunning -> False]

enter image description here

How can I keep in the second animation the same legend colors for the different names (this is the case, as in animation 1) but in the sorted bar chart these colors have to be rearranged corresponding to the counts.

$\endgroup$
5
$\begingroup$

I don't want to delete any part of your codes to make a MWE, but since there are lots of options in them I'll go step-by-step to highlight what I have done.

First, your first Animate, in its entirety:

counts = 101;
names = Sort[{"name01", "name02", "name03", "name04", "name05"}];
nbars = Length[names];

maxRandomNumber = 1;

data = Array[0 &, {nbars, counts}];

Do[data[[All, i]] = 
    data[[All, i - 1]] + RandomInteger[maxRandomNumber, nbars];, {i, 
   2, counts}];

Animate[pl = 
  BarChart[data[[All, i + 1]], ImagePadding -> All, Frame -> True, 
   ChartStyle -> "BlueGreenYellow", 
   PlotRange -> {{0, nbars + 1}, {0, 1.1*Max@Flatten@data}}, 
   ImageSize -> 600, 
   ChartLabels -> Placed[names, Axis, Rotate[#, -Pi/2] &], 
   LabelingFunction -> (Placed[Panel[#1, FrameMargins -> 0], 
       Above] &), FrameLabel -> {{"votes", ""}, {"names", ""}}, 
   ChartLegends -> names], {i, 0, counts - 1, 1, 
  Appearance -> "Labeled"}, AnimationRepetitions -> 1, 
 DefaultDuration -> 20, AnimationRunning -> False]

The only change so far is that I gave a name, pl to the BarChart (right after Animate[).

enter image description here

Second, I extract the colors from pl (credit to Sumit):

colors = Cases[pl, RGBColor[x_, y_, z_] :> RGBColor[x, y, z], 
   Infinity][[-nbars ;; -1]]

The colors could be also obtained with ColorData:

colors = Table[ColorData["BlueGreenYellow"][i], {i, 0, 1, 0.25}]

as pointed out by Feyre.


I keep them as RGBColor so I can use them without further alterations.

In the second, sorted, animation, I use ChartStyle -> colors[[Ordering[#, All, Greater]& @ data[[All, i + 1]]]]. The reasoning is that I use Ordering to get the initial (i.e., before you apply Sort[..., Greater]) order of data[[All, i+1]]; let's call it order for a moment. Then I rearrange the colors according to the same order - basically, I do colors[[order]]. Finally, I directly feed the colors to the ChartStyle:

Animate[BarChart[Sort[data[[All, i + 1]], Greater], 
  ImagePadding -> All, Frame -> True, 
  ChartStyle -> 
   colors[[Ordering[#, All, Greater] &@data[[All, i + 1]]]], 
  PlotRange -> {{0, nbars + 1}, {0, 1.1*Max@Flatten@data}}, 
  ImageSize -> 600, 
  ChartLabels -> 
   Placed[names[[Ordering[#, All, Greater] &@data[[All, i + 1]]]], 
    Axis, Rotate[#, -Pi/2] &], 
  LabelingFunction -> (Placed[Panel[#1, FrameMargins -> 0], Above] &),
   FrameLabel -> {{"votes", ""}, {"names", ""}}, 
  ChartLegends -> 
   names[[Ordering[#, All, Greater] &@data[[All, i + 1]]]]], {i, 
  0, counts - 1, 1, Appearance -> "Labeled"}, 
 AnimationRepetitions -> 1, DefaultDuration -> 20, 
 AnimationRunning -> False]

enter image description here

Notice that I also changed ChartLabels and ChartLegends from names to names[[order]].


EDIT: ChartLegends had to be changed from names to names[[order]] for the colors to match the names. This alters the ordering of the displayed names, i.e. name03 is first, instead of name01. To have it in order I produce a SwatchLegend (which is used by BarChart by default, so it will look consistent):

legend = SwatchLegend[colors, names]

enter image description here

Then just type ChartLegends -> legend.

$\endgroup$
  • $\begingroup$ This is exactly the solution ... perfect, thank you for your help and explanation. $\endgroup$ – lio Oct 24 '16 at 19:54
  • 1
    $\begingroup$ Cases[pl, RGBColor[x_, y_, z_] :> RGBColor[x, y, z], Infinity] is an odd bit of code; the rule appears superfluous. Consider Cases[pl, _RGBColor, Infinity] instead, or Cases[pl, _RGBColor?ColorQ, Infinity] for robustness. $\endgroup$ – Mr.Wizard Oct 24 '16 at 20:31
  • $\begingroup$ How can I keep the ChartLegends with the orginal colors and alphabetical order unchanged during each evaluation step? $\endgroup$ – lio Oct 25 '16 at 20:05
  • 1
    $\begingroup$ @lio See the edit. $\endgroup$ – corey979 Oct 25 '16 at 20:44
  • 1
    $\begingroup$ @lio I would use ColorData myself, as already shown in the answer above. For more of my thoughts on extracting style information from plots see mathematica.stackexchange.com/a/123155/121 $\endgroup$ – Mr.Wizard Oct 26 '16 at 12:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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