6
$\begingroup$

Description:

I would like to enforce consistent legend and style throughout dynamic PieChart evaluation.

Problem:

Based on current implementation, the color and legend associated with particular datasets switch throughout evaluation.

Example:

DynamicModule[
 {n = 20},
 Column[{
   Row[{Slider[Dynamic[n], {1, 100, 1}], Dynamic[n]}],
   Dynamic[
    PieChart[#[[All, 2]], ChartLegends -> #[[All, 1]], 
       ChartStyle -> {Green, Red}] & @ 
     Tally @RandomChoice[{True, False}, n]]
   }]
 ]

Output:

output1
output2
output3

How could I enforce Legend to include both True and False; where True to be always represented in Green and False in Red? I would also like True to come before False in the Legend.

$\endgroup$
4
  • 1
    $\begingroup$ If you do Sort@Tally@RandomChoice... it'll sort the values first and won't have this problem. $\endgroup$
    – N.J.Evans
    Commented May 26, 2016 at 16:02
  • $\begingroup$ @N.J.Evans partially, it does. There is however another issue which is related to the question. Please let me edit OP. $\endgroup$ Commented May 26, 2016 at 16:05
  • $\begingroup$ Use trueFalseTally[list_] := {#, Count[list, #]} & /@ {True, False}; instead of Tally It will return {{True,numTrues},{False,numFalses}}` even if there aren't any, then your plot will format correctly. $\endgroup$
    – N.J.Evans
    Commented May 26, 2016 at 16:23
  • $\begingroup$ @N.J.Evans Appreciate that, leave your answer. I will leave the question open for some time to see what people think. If there is no other solutions, I will be happy to accept your answer $\endgroup$ Commented May 26, 2016 at 16:28

2 Answers 2

5
$\begingroup$
DynamicModule[{n = 20}, 
 Column[{Row[{Slider[Dynamic[n], {1, 100, 1}], Dynamic[n]}], 
   Dynamic[Legended[PieChart[Thread[Style[#[[All, 2]], #[[All, 1]] /.
        {True -> Red, False -> Green}] ], 
      ChartStyle -> {Green, Red}] &@ 
      Tally@RandomChoice[{True, False}, n], 
     SwatchLegend[{Green, Red}, {False, True}]]]}]]

Mathematica graphics

Mathematica graphics

Alternatively (thanks: Brett Champion):

DynamicModule[{n = 20}, 
 Column[{Row[{Slider[Dynamic[n], {1, 100, 1}], Dynamic[n]}], 
   Dynamic[PieChart[Thread[Style[#[[All, 2]], #[[All, 1]] /. 
                      {True -> Red, False -> Green}]], 
       ChartLegends -> SwatchLegend[{Green, Red}, {False, True}]] &@
     Tally@RandomChoice[{True, False}, n]]}]]
$\endgroup$
5
  • 2
    $\begingroup$ You can also pass the SwatchLegend to ChartLegends: ChartLegends -> SwatchLegend[{Green, Red}, {True, False}] $\endgroup$ Commented May 26, 2016 at 18:49
  • $\begingroup$ This fails in the case that n=1 and RandomChoice returns True. Since Tally only returns an entry for True, your ChartStyle applies Green to the True value, even though the legend is correct. $\endgroup$
    – N.J.Evans
    Commented May 26, 2016 at 19:28
  • $\begingroup$ I think all the code should be checked carefully as to whether green is true or false... $\endgroup$ Commented May 26, 2016 at 19:30
  • $\begingroup$ @N.J.Evans, thank you. I will update with a fix. $\endgroup$
    – kglr
    Commented May 26, 2016 at 19:40
  • $\begingroup$ @Brett and N.J. Evans, thank you for the comments. I hope the updated version fixes the issue you mention. $\endgroup$
    – kglr
    Commented May 26, 2016 at 19:51
4
$\begingroup$

The Red/Green problem stems from the fact that Tally returns tallied values in the order each element is first encountered, and the other issue is because Tally doesn't return a 0 entry for elements not in the list. Both issues can be solved with a custom tally:

explicitTally[list_,toTally_List] := {#, Count[list, #]} & /@ toTally;

If you use explicitTally[#,{True,False}] in place of Tally everything should work correctly. Use is shown below, I also used Transpose and Apply (@@) to clean it up a little.

DynamicModule[
 {n = 20},
 Column[{
   Row[{
     Slider[Dynamic[n], {1, 100, 1}],
     Dynamic[n]
     }],
   Dynamic[
    PieChart[
       #2,
       ChartLegends -> #1,
       ChartStyle -> {Green, Red}
       ] & @@ 
     Transpose@
      explicitTally[RandomChoice[{True, False}, n], {True, False}]
    ]
   }]
 ]
$\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.