11
$\begingroup$

Let's say I have two samples:

data1 = RandomChoice[DateRange[{2010, 1, 1}, {2010, 4, 31}, "Day"], 100];
data2 = RandomChoice[DateRange[{2010, 5, 1}, {2010, 8, 31}, "Day"], 100];

I want to plot a histogram with both of them, and I want data2's bars to have Dotted or Dashed EdgeForm depending of a value of some variable, let's say t.

Problems with available styling options:

  • Dynamic @ DateHistogram[...], recreating it will be too slow for bigger samples.

  • ChartStyle can't be Dynamic or contain it in a list. It can have Directives but they can't contain Dynamic either so it won't work as a wrapper.

  • ChartElementFunction does not allow to distinguish data samples.

  • Histogram* allows certain wrappers for data, e.g. Style: Style[data2, Orange] but it won't allow Dynamic inside

The only way I was able to use is a hairy postprocessing:

t = True; Checkbox @ Dynamic @ t

DateHistogram[
    {data1, data2}, ChartStyle -> {Green, Red} 
] /. d_Directive :> Which[
   MemberQ[d, Red, ∞], 
   Dynamic[
     Directive[##, EdgeForm[If[TrueQ[t], Dashed, Dotted]]]
   ] & @@ d
   ,
   True, 
   d
]

enter image description here

Is there a more stable/generic way to achieve this?

$\endgroup$
5
  • $\begingroup$ Nested Directives complicate post-processing too much. Why Directive isn't Flat?! I see no reason to keep nested structures of Directives. $\endgroup$ Commented Aug 18, 2016 at 10:15
  • $\begingroup$ @AlexeyPopkov That is another question but can live with this. $\endgroup$
    – Kuba
    Commented Aug 18, 2016 at 10:17
  • $\begingroup$ Is DateHistogram (which I don't have) necessary for this example or could you be using a Histogram instead? $\endgroup$
    – Mr.Wizard
    Commented Aug 18, 2016 at 11:39
  • $\begingroup$ Sorry, I've got nothing. Alexey's method looks good to me. $\endgroup$
    – Mr.Wizard
    Commented Aug 18, 2016 at 12:32
  • $\begingroup$ @Mr.Wizard in case of Histogram I can use HistogramList to assemble Graphics by myself and have a full control. But for DateHistogram it is not possible :/ HistogramList for DateHistogram? $\endgroup$
    – Kuba
    Commented Aug 18, 2016 at 12:33

4 Answers 4

3
$\begingroup$

A better post-processing approach

You can use Annotation (or Hyperlink or Button) as a wrapper for the data with a tag as the second argument for simplification of the post-processing:

DateHistogram[{data1, Annotation[data2, myTag]}] /. 
 Annotation[d_, myTag] :> Sequence[Dynamic[EdgeForm[If[TrueQ[t], Dashed, Dotted]]], d]

This is much simpler and more stable/generic than the method shown in the question, but it still depends on the specifics of the current implementation of DateHistogram.


A hackish solution

Another way is to fool the internal check for validness of style directives by wrapping the tag with Glow (other possibilities: Specularity, RGBColor, Opacity, GrayLevel; checked with Mathematica 11.0.0):

DateHistogram[{data1, data2}, ChartStyle -> {Green, Glow[myTag]}] /. 
 d_Directive /; MemberQ[d, Glow[myTag], ∞] :> 
  Sequence[d /. Glow[myTag] :> {}, Dynamic[EdgeForm[If[TrueQ[t], Dashed, Dotted]]]]

Shorter version:

DateHistogram[{data1, Style[data2, Glow[myTag]]}] /. 
 Directive[Glow[myTag]] :> Dynamic[EdgeForm[If[TrueQ[t], Dashed, Dotted]]]

Of course this method potentially can be broken in future if there will be introduced a check for validness of arguments of Glow etc. Hence the method shown in the previous section is preferable.

$\endgroup$
2
$\begingroup$

A worse post-processing approach

I messed around with this for a while and this is the best I could do.

data = RandomVariate[NormalDistribution[#, 3], 100] & /@ {-1, 5};

t = True; Checkbox@Dynamic@t

MapAt[
  # /. _FEPrivate`If :> EdgeForm[If[t, Dashed, Dotted]] &,
  Histogram[data, ChartStyle -> {Green, Red}],
  {1, 1, 2, 2}
]

The second 2 in {1, 1, 2, 2} may be changed to target the styling. Hey, I said it was worse. :^)

YAPPM

(Yet another post-processing method.) The same thing you did but less focused.

Histogram[data, ChartStyle -> {Green, Red}] /.
  x_Directive :> Dynamic[x] /. 
    x : Red :> {x, EdgeForm[If[t, Dashed, Dotted]]}
$\endgroup$
4
  • $\begingroup$ Look out for PerformanceGoal -> "Speed" too. $\endgroup$
    – Kuba
    Commented Aug 18, 2016 at 13:26
  • $\begingroup$ @Kuba Yes, I'm sure this is quite fragile. :-( $\endgroup$
    – Mr.Wizard
    Commented Aug 18, 2016 at 13:26
  • 1
    $\begingroup$ @Mr.Wizard Thank you for posting this answer! I won't upvote it but I express thanks because I was much wondered whether there is a straightforward way to solve this problem. Now I'm sure there is no way and the reason is clear: Directive doesn't accept Dynamic style directives. But WHY? I don't see any reason for this! $\endgroup$ Commented Aug 18, 2016 at 13:48
  • 1
    $\begingroup$ @Alexey I don't know; it doesn't seem to be easy to get an answer to questions like that. I am glad you found something in this answer useful; I regularly find your answers quite enlightening. $\endgroup$
    – Mr.Wizard
    Commented Aug 18, 2016 at 13:57
2
$\begingroup$

You could specify the low-level parameter of the Dashing:

t = Small;
Checkbox[Dynamic[t], {Small, 0}]
DateHistogram[{data1, 
  Style[data2, EdgeForm[Dashing[{Dynamic@t, Small}]]]}]
$\endgroup$
3
  • $\begingroup$ +1 Nice, sadly it is not general :(, e.g. controlling colors. $\endgroup$
    – Kuba
    Commented Sep 2, 2016 at 5:36
  • $\begingroup$ @Kuba not sure if I understand you correctly. ChartStyle -> {Green, Red} can still be added as an option for DateHistogram. $\endgroup$ Commented Sep 2, 2016 at 19:48
  • $\begingroup$ I meant to link it dynamically to e.g ColorSetter. $\endgroup$
    – Kuba
    Commented Sep 2, 2016 at 20:05
1
$\begingroup$

You may apply Dynamic to the entire DateHistogram.

Checkbox[Dynamic@t, {Dashed, Dotted}]

Then

Dynamic@DateHistogram[{data1, data2}, 
  ChartStyle -> {Green, Directive@{Red, EdgeForm[t]}}]

Hope this helps.

$\endgroup$
1
  • 1
    $\begingroup$ +1 For simple cases it is a good solution I forgot to mention but I came here because it was not enough for large datasets. Recalculating whole plot takes to much time then. $\endgroup$
    – Kuba
    Commented Aug 19, 2016 at 5:26

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.