10
$\begingroup$

I have multiple ListPlot in a Show where i want to add PlotLegends, but adding the PlotLegend attribute inside of each ListPlot adds a legend without any color representation, which is useless.

How do i deal with this in Mathematica 9?

Code sample:

dataamountofruns1 = 
  Import["/Statistics/initial_test/initial_1_stat.csv", 
   "CSV"];
dataamountofruns2 = 
  Import["/Statistics/initial_test/initial_2_stat.csv", 
   "CSV"];
dataamountofruns3 = 
  Import["/Statistics/initial_test/initial_3_stat.csv", 
   "CSV"];
Show[
 ListPlot[dataamountofruns1, PlotStyle -> Blue,],
 ListPlot[dataamountofruns2, PlotStyle -> Green],
 ListPlot[dataamountofruns3, PlotStyle -> Orange],
 AxesStyle -> Black,
 FrameLabel -> {"Generation", "Population"},
 Frame -> True,
 FrameTicks -> All,
 ImageSize -> 600,
 Background -> Transparent,
 PlotRange -> All,
 BaseStyle -> {12, FontFamily -> "Helvetica"}
 ]

enter image description here

$\endgroup$
  • 1
    $\begingroup$ It would be very useful if you could provide at least a small sample of the three .csv files, so as we could play with them. $\endgroup$ – Vaggelis_Z Jul 1 '14 at 11:56
10
$\begingroup$

Here is the example of how to make this with Epilog:

(* These are the list and a function to fit it that will be plotted *)   
lst = Transpose[{RandomReal[{0, 3}, 30], 
     RandomReal[{-0.03, 0.03}, 30]}] /. {x_, y_} -> {x, x*Exp[-x] + y};
ft = FindFit[lst, a + b*x*Exp[-c*x], {a, b, c}, x];
(* End ofg the list and fitting function *)

(* The show statements begins  *)
Show[{
  ListPlot[lst, PlotRange -> {{0, 3.5}, Automatic}
   ],

  Plot[a + b*x*Exp[-c*x] /. ft, {x, 0, 3}, 
   PlotRange -> {{0, 3.5}, Automatic}, PlotStyle -> Red]
  },

 (* The legends in the Epilog are starting here *)
 Epilog -> Inset[Framed[Column[{
      PointLegend[{Blue}, {"    Data"}],
      LineLegend[{Red}, \
{"f(x)=\!\(\*SuperscriptBox[\(x\[ExponentialE]\), \(-x\)]\)"}]
      }], RoundingRadius -> 5], Scaled[{0.8, 0.85}]]
 (* End of the Legends *)
  ]

It should look like this: enter image description here

The same might be done using the Prolog. The difference is only visible, if the legends overlaps with the plots.

Another way is to place Legends into each Plot or ListPlot statement. The example using the same list and fitting function is given below. Then it lacks the common frame.

    Show[{
    ListPlot[lst, PlotRange -> {{0, 3.5}, Automatic},

      (* The PointLegend starts *)
      PlotLegends -> 
    Placed[PointLegend[{"    data"}, LabelStyle -> {Blue, 10}], 
     Scaled[{0.69, 0.9}]]
      (* The PointLegend ends *)
      ],

    Plot[a + b*x*Exp[-c*x] /. ft, {x, 0, 3}, 
   PlotRange -> {{0, 3.5}, Automatic}, PlotStyle -> Red,

      (* The LineLegend starts *)
   PlotLegends -> 
    Placed[LineLegend[{Row[{Style["f(x)=", Italic], 
         Style[NumberForm[a + b*x*Exp[-c*x] /. ft, {2, 1}], 
          Italic]}]}, LabelStyle -> {Red, 10}], Scaled[{0.8, 0.8}]]]
    (* The LineLegend ends *)

    }]

It should look like the following: enter image description here

Edit: To address the question about the spacing between the legends. It is easy to do in the case of the second method, since in this case there are two different legends, each having been created within its own Plot statement. Thea are then placed one under the other, and the point in which the second one is placed was chosen by me. Like this I can easily choose another point instead. Please see the example below. There the parameter z defines the displacement of the second legend from its initial position. Play with the slider to see its effect:

 lst = Transpose[{RandomReal[{0, 3}, 30], 
     RandomReal[{-0.03, 0.03}, 30]}] /. {x_, y_} -> {x, x*Exp[-x] + y};
ft = FindFit[lst, a + b*x*Exp[-c*x], {a, b, c}, x];

Manipulate[
 Show[{ListPlot[lst, 
    PlotRange -> {{0, 3.5}, Automatic},(*The PointLegend starts*)
    PlotLegends -> 
     Placed[PointLegend[{"    data"}, LabelStyle -> {Blue, 10}], 
      Scaled[{0.69, 0.9}]]
    (*The PointLegend ends*)], 
   Plot[a + b*x*Exp[-c*x] /. ft, {x, 0, 3}, 
    PlotRange -> {{0, 3.5}, Automatic}, 
    PlotStyle -> Red,(*The LineLegend starts*)
    PlotLegends -> 
     Placed[LineLegend[{Row[{Style["f(x)=", Italic], 
          Style[NumberForm[a + b*x*Exp[-c*x] /. ft, {2, 1}], 
           Italic]}]}, LabelStyle -> {Red, 10}], 
      Scaled[{0.8, 0.8 - z}]]]
   (*The LineLegend ends*)}], {z, 0, 0.5}]

You should see the following:

enter image description here

In principle one can change the spacing also within the first approach. Under the Epilog-Inset... You find the statement Column there. In principle, one should be able to insert the statement Spacer between the first and the second argument of the Column as follows: Column[{statement1, Spacer[z],statement2}] and play with the numeric value of z. However, this did not work for me. Looks as a bug, though I am not sure. If you only need to increase the distance between the lines in the legend you might choose to enter something invisible between the first and the second argument of the Column. For example, you can do it as follows:

Manipulate[
 Show[{ListPlot[lst, PlotRange -> {{0, 3.5}, Automatic}], 
   Plot[a + b*x*Exp[-c*x] /. ft, {x, 0, 3}, 
    PlotRange -> {{0, 3.5}, Automatic}, 
    PlotStyle -> Red]},(*The legends in the Epilog are starting here*)
  Epilog -> 
   Inset[Column[{PointLegend[{Blue}, {"    Data"}], Style["", z], 
      LineLegend[{Red}, \
{"f(x)=\!\(\*SuperscriptBox[\(x\[ExponentialE]\), \(-x\)]\)"}]}], 
    Scaled[{0.8, 0.85}]]
  (*End of the Legends*)], {z, 10, 50}]

Here I added an empty string, but the distance varies due to the variation of the size of the absent text. Play with the slider to see the effect.

Have fun!

$\endgroup$
  • $\begingroup$ Is there any way to set the line spacing in the legends? $\endgroup$ – H. R. Sep 6 at 22:23
  • 1
    $\begingroup$ @H. R. Please have a look at the edits $\endgroup$ – Alexei Boulbitch Sep 16 at 9:24
5
$\begingroup$

You could combine all your data into list plot and then use PlotLegends. If you wish.need to use Show you could use Legended.

Here is an example with toy data:

data1 = MapThread[
   1/(1 + Exp[- #1 + #2]) &, {Range[0, 20, 1], 
    RandomReal[{0, 1}, 21]}];
data2 = MapThread[
   1/(1 + Exp[- 1.4 #1 + #2]) &, {Range[0, 20, 1], 
    RandomReal[{0, 1}, 21]}];
data3 = MapThread[
   1/(1 + Exp[-0.6 #1 + #2]) &, {Range[0, 20, 1], 
    RandomReal[{0, 1}, 21]}];

Combining data:

 ListPlot[{data1, data2, data3}, PlotMarkers -> {Automatic, 10}, 
  PlotLegends -> {"a", "b", "c"}]

enter image description here

Using Show

Legended[Show[
  MapThread[
   ListPlot[#1, PlotStyle -> #2] &, {{data1, data2, data3}, 
    op = {Directive[Red, AbsolutePointSize[7]], 
      Directive[Green, AbsolutePointSize[7]], 
      Directive[Blue, AbsolutePointSize[7]]}}]], 
 PointLegend[op, {"a", "b", "c"}]]

enter image description here

$\endgroup$
4
$\begingroup$

Another simple solution following your first idea

"adding the PlotLegend attribute inside of each ListPlot adds a legend without any color representation"

You can force Mathematica to show a colour-coded legend for a single dataset by specifying the format of the legend using one of the "LineLegend","SwatchLegend","PointLegend", etc... commands.

In your code it would look like this (using LineLegend)

...
Show[
 ListPlot[dataamountofruns1, PlotStyle -> Blue, PlotLegends -> LineLegend[{"A"}]],
 ListPlot[dataamountofruns2, PlotStyle -> Green, PlotLegends -> LineLegend[{"B"}]],
 ListPlot[dataamountofruns3, PlotStyle -> Orange, PlotLegends -> LineLegend[{"C"}]],
 AxesStyle -> Black,
 FrameLabel -> {"Generation", "Population"},
...]

Should generate something like this...

Legend example

Typically I use something like this when I need to combine the outputs of Plots and LinePlots

$\endgroup$
  • $\begingroup$ Welcome! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour and check the faqs! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$ – user9660 Sep 12 '16 at 17:34
2
$\begingroup$

In earlier versions (and also v.9), to use a legend with Show use ShowLegend :-

dataamountofruns1 = Table[4 Log[x], {x, 1, 700}];
dataamountofruns2 = Table[3 Log[x], {x, 1, 700}];
dataamountofruns3 = Table[2 Log[x], {x, 1, 700}];

Needs["PlotLegends`"];

 ShowLegend[Show[
  ListPlot[dataamountofruns1, PlotStyle -> Blue],
  ListPlot[dataamountofruns2, PlotStyle -> Green],
  ListPlot[dataamountofruns3, PlotStyle -> Orange],
  AxesStyle -> Black, FrameLabel -> {"Generation", "Population"},
  Frame -> True, FrameTicks -> All, ImageSize -> 600,
  Background -> Transparent,
  PlotRange -> All, BaseStyle -> {12, FontFamily -> "Helvetica"}],
 {{{Graphics[{Blue, Rectangle[{0, 0}]}],
    Style["Initial 1", 12, FontFamily -> "Helvetica"]},
   {Graphics[{Green, Rectangle[{0, 0}]}],
    Style["Initial 2", 12, FontFamily -> "Helvetica"]},
   {Graphics[{Orange, Rectangle[{0, 0}]}],
    Style["Initial 3", 12, FontFamily -> "Helvetica"]}},
  LegendPosition -> {0.25, -0.35}, LegendTextSpace -> 1.5,
  LegendSize -> {0.4, 0.25}, LegendShadow -> False, 
  LegendBorderSpace -> 0.5}]

enter image description here

In version 9, as demonstrated by ubpdqn, Legended can be used :-

dataamountofruns1 = Table[4 Log[x], {x, 1, 700}];
dataamountofruns2 = Table[3 Log[x], {x, 1, 700}];
dataamountofruns3 = Table[2 Log[x], {x, 1, 700}];

Legended[Show[
  ListPlot[dataamountofruns1, PlotStyle -> Blue],
  ListPlot[dataamountofruns2, PlotStyle -> Green],
  ListPlot[dataamountofruns3, PlotStyle -> Orange],
  AxesStyle -> Black, FrameLabel -> {"Generation", "Population"},
  Frame -> True, FrameTicks -> All, ImageSize -> 560,
  Background -> Transparent,
  PlotRange -> All, BaseStyle -> {12, FontFamily -> "Helvetica"}],
 Placed[SwatchLegend[{Blue, Green, Orange},
   {Style["Initial 1", 12],
    Style["Initial 2", 12],
    Style["Initial 3", 12]},
   LegendMargins -> {{15, 15}, {5, 5}}, LegendFunction -> Framed,
   LabelStyle -> (FontFamily -> "Helvetica")], {{0.7, 0.1}, {0, 0}}]]

enter image description here

$\endgroup$
1
$\begingroup$

I don't have your actual data to work with them but I think that this is what you want

S0 = ListLinePlot[{dataamountofruns1, dataamountofruns2, dataamountofruns3},
Joined -> False, PlotStyle -> {Blue, Green, Orange}, Axes -> False, 
AxesStyle -> Black, FrameLabel -> {"Generation","Population"}, 
Frame -> True, FrameTicks -> All, ImageSize -> 600, 
Background -> Transparent, PlotRange -> All,
BaseStyle -> {12, FontFamily -> "Helvetica"}, 
PlotLegends -> 
Placed[{Style["data1", FontFamily -> "Helvetica", 18], 
Style["data2", FontFamily -> "Helvetica", 18], 
Style["data3", FontFamily -> "Helvetica", 18]}, 
Scaled[{0.85, 0.25}]]]
$\endgroup$

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.