11
$\begingroup$

This plot has 40 curves on the same graph which makes it hard to see.
I need to plot them on one graph. So I have an idea to plot to make it easier to see which one is larger or smaller in each range.
The idea is that to plot them and each one is linked with a radio button or something so that you can look at the graph and decide to hide or unhide any curve you want to make it easier to compare.
How can I implement this? Would it be possible to make it hide with gray color instead of completely invisible? Or is there any other idea?
The function below is just for this example. My real function is more complex.

f[a_, b_, c_] := (a*x^2 + b*x + c)/3;
tup1 := RandomInteger[5, {40, 3}];
Plot[f[##] & @@@ tup1 // Evaluate, {x, 0, 5}, GridLines -> Automatic]
$\endgroup$
2
  • $\begingroup$ @cvgmt it's still difficult to compare as two many curves. My idea is that once it's plot I can look at each curve and decide hide curves that are not interested. $\endgroup$
    – emnha
    Commented Feb 8, 2021 at 11:51
  • $\begingroup$ A related question. $\endgroup$ Commented Feb 9, 2021 at 12:26

2 Answers 2

23
$\begingroup$

Update 2: We can combine a toggler-bar legend and FlipView to control curve visibility by clicking on curves and/or legends. (Naturally this approach is less responsive than either method.)

f[a_, b_, c_] := (a x^2 + b x + c)/3;

tup1 := RandomInteger[5, {40, 3}];

tup = tup1;

functions = f @@@ tup;

colors = ColorData[97] /@ Range[Length @ functions];

functionswithtooltips = MapThread[Tooltip, {functions, tup}];

First we plot functionswithtooltips and extract the primitives:

plot1 = Plot[Evaluate[functionswithtooltips], {x, 0, 5}, 
   GridLines -> Automatic, ImageSize -> Large, 
   PlotStyle -> Thread[Directive[colors, Opacity[.3], Thin]]];
ttlist = Cases[plot1, _Tooltip, All];

Note: In versions 13.3+, add the option PlotHighlighting -> None in definition of plot1 above.

Then we turn each tooltipped line into an EventHandler and add the necessary updating to dynamic variables:

Deploy @ DynamicModule[{n = {1}, hidden = ConstantArray[1, Length @ ttlist]},
  hidden[[n]] = 2; 
  Dynamic[Legended[
    Graphics[Table[With[{i = i, ind = hidden[[i]]}, 
       Tooltip[{ttlist[[i, 1, 1]], 
         DynamicModule[{boxes = {ttlist[[i, 1, 2]], 
             Style[ttlist[[i, 1, 2]], Opacity[1], Thickness[Large]]}, 
           index = ind, length = 2}, 
          EventHandler[Dynamic[boxes[[index]]], 
            {"MouseClicked" :> (index = index /. {1 -> 2, 2 -> 1}; 
                  hidden[[i]] = index; n = Flatten[Position[hidden, 2]];), 
             Method -> "Preemptive",
             PassEventsDown -> True, PassEventsUp -> True}], 
          DynamicModuleValues :> {}]}, 
       ttlist[[i, 2]]]], {i, 1, Length @ ttlist}], 
     ImageSize -> 700, AspectRatio -> 1/GoldenRatio, 
     PlotRange -> {{0, 5}, {0, 50}}, Frame -> True],
    TogglerBar[Dynamic[n, (n = #; hidden[[All]] = 1; hidden[[n]] = 2) &], 
     MapIndexed[
       #2[[1]] -> Style[#, 16, Bold, Opacity[1], colors[[#2[[1]]]]] &, tup],
     Appearance -> "Vertical" -> {Automatic, 4}]]]]

enter image description here

Update: We can use FlipView to interactively hide/show a curve:

plot1 = Plot[Evaluate[functionswithtooltips], {x, 0, 5}, 
   GridLines -> Automatic, ImageSize -> Large, 
   PlotStyle -> Thread[Directive[colors, Opacity[.3], Thin]]];

plot1 /. l_Line :> 
   FlipView[{l, Style[l, Opacity[1], Thick]}] // Deploy

enter image description here

Original answer:

You can use TogglerBar as legend panel to hide/show any subset of lines:

f[a_, b_, c_] := (a x^2 + b x + c)/3;
tup1 := RandomInteger[5, {40, 3}];

tup = tup1;
functions = f @@@ tup;

colors = ColorData[97] /@ Range[Length @ functions];

Dynamic[Legended[Plot[functions, {x, 0, 5}, GridLines -> Automatic, 
    ImageSize -> Large, 
    PlotStyle -> ReplacePart[colors, {Except[Alternatives @@ n]} -> None]], 
  TogglerBar[Dynamic[n], 
     MapIndexed[
        #2[[1]] -> Style[#,16, Bold, Opacity[1], colors[[#2[[1]]]]] &, tup],
   Appearance -> "Vertical" -> {Automatic, 4}]]]

enter image description here

You can add tooltips and play with opacity and thickness rather than making lines completely invisible:

functionswithtooltips = MapThread[Tooltip, {functions, tup}];

DynamicModule[{n = {1}}, 
 Dynamic[Legended[Plot[Evaluate @ functionswithtooltips , {x, 0, 5}, 
    GridLines -> Automatic, ImageSize -> Large, 
    PlotStyle -> (Thread[Directive[colors, Opacity[.3], Thin]] /. 
       Directive[a : Alternatives @@ colors[[n]], _, _] :> 
        Directive[a, Opacity[1], AbsoluteThickness[3]])], 
   TogglerBar[Dynamic[n], 
    MapIndexed[
      #2[[1]] -> Style[#, 16, Bold, Opacity[1], colors[[#2[[1]]]]] &, tup],
    Appearance -> "Vertical" -> {Automatic, 4}]]]]

enter image description here

$\endgroup$
14
  • 2
    $\begingroup$ very nice figure $\endgroup$
    – emnha
    Commented Feb 8, 2021 at 14:27
  • $\begingroup$ Would it be possible to select a curve on the graph and it shows me which parameter combination is it on the right too? $\endgroup$
    – emnha
    Commented Feb 8, 2021 at 23:06
  • $\begingroup$ Thanks. That is same as what I was thinking . Would it be OK to highlight the parameter combination somehow so when I click on a curve and if I want to hide it then I can immediately locate its location to hide? Current version is nice too. Just thinking if that can be done easily from this. $\endgroup$
    – emnha
    Commented Feb 9, 2021 at 3:39
  • 1
    $\begingroup$ @anhnha, replace None with Opacity[.3, Gray] or with Directive[Opacity[.3], Gray]. $\endgroup$
    – kglr
    Commented Feb 24, 2021 at 23:24
  • 1
    $\begingroup$ @anhnha, not sure which color scheme has the best contrast (that sounds like a good new question). To put more space between plot and legend in Legended[plot, legend] you can use Legended[plot, Row[{Spacer[10], legend}]] and play with different values instead of 10. $\endgroup$
    – kglr
    Commented Feb 24, 2021 at 23:43
1
$\begingroup$

Just a list of other alternatives (as only a toy example is given in the above question):

  • When one has many curves one might consider plotting all possible pairwise plots of the parameters as the "information" about the curves is complete contained in those parameters (if we ignore the error variance for the moment). Each point could be labeled as to its source.

  • If there are many parameters, then other summary statistics that make some sort of subject matter sense could be plotted against each other. For example, if dealing with insecticides and a logistic
    regression, then plotting the LD50 (Lethal Dose that kills 50% of the critters) and the LD95 against each other might be a good and compact summary that makes sense to those subject matter experts. (This matches the OP's statement "So I have an idea to plot to make it easier to see which one is larger or smaller in each range.".)

$\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.