8
$\begingroup$

I used Show to combine a ListPlot and Plot, and each plot has its own legend. The code is as follows:

    list1 = 
    {{0.1, 0.3}, {0.3, 0.42}, {0.5, 0.48}, {0.7, 0.57}, {0.9, 0.72}};
    list2 =
    {{0, 0.2}, {0.2, 0.25}, {0.4, 0.31}, {0.6, 0.34}, {0.8, 0.39}};
    curve1[x_] := 0.25 + 0.5 x; curve2[x_] := 0.2 + 0.25 x;
    p1 = ListPlot[{list1, list2}, PlotRange -> {{0, 1}, {0, 0.8}}, 
    PlotStyle -> {{Red}, {Orange}}, Frame -> True, 
    PlotLegends -> Placed[PointLegend[{"Experimental data 1", 
    "Experimental data 2"}], {0.8, 0.3}], ImageSize -> Large];
    p2 = Plot[{curve1[x], curve2[x]}, {x, 0, 1}, 
    PlotRange -> {{0, 1}, {0, 0.8}}, 
    PlotStyle -> {Blue, Black}, Frame -> True, 
    PlotLegends -> Placed[LineLegend[{"Theoretical line for data 1", 
    "Theoretical line for data 2"}], {0.8, 0.2}], ImageSize -> Large];
    Show[p1, p2]

plot

Now I want the four legends to have the same vertical spacing between each other, and the beginning letter "E" and "T" to be exactly aligned in vertical direction. How can I do that?

$\endgroup$

3 Answers 3

6
$\begingroup$

Update: A much easier way is to use single LineLegend with point and line elements:

mixedlegend = LineLegend[{White, White, Blue, Black}, 
{"Experimental data 1",  "Experimental data 2",
 "Theoretical line for data 1", "Theoretical line for data 2"}, 
  LegendMarkers -> {Graphics[{Red, Disk[]}], Graphics[{Orange, Disk[]}], None, None}]

enter image description here

Legended[Show[p1a, p2a], Placed[mixedlegend, {Scaled[.8], Scaled[.2]}]]

enter image description here

Plot[{curve1[x], curve2[x]}, {x, 0, 1}, 
 PlotRange -> {{0, 1}, {0, 0.8}}, PlotStyle -> {Blue, Black}, 
 Frame -> True, ImageSize -> Large, Epilog -> p1a[[1]], 
 PlotLegends -> Placed[mixedlegend, {Scaled[.8], Scaled[.2]}]]
(* same picture *)

Original post:

You can play with LegendMarkerSize manually to align the texts:

p1a = ListPlot[{list1, list2}, PlotRange -> {{0, 1}, {0, 0.8}}, 
   PlotStyle -> {Directive[Red, PointSize[Large]], 
     Directive[Orange, PointSize[Large]]}, Frame -> True, ImageSize -> Large];

p2a = Plot[{curve1[x], curve2[x]}, {x, 0, 1}, 
   PlotRange -> {{0, 1}, {0, 0.8}}, PlotStyle -> {Blue, Black}, 
   Frame -> True, ImageSize -> Large];

legend = Column[{PointLegend[{Red, Orange},
          {"Experimental data 1", "Experimental data 2"}, 
          LegendMarkers -> {"\[FilledCircle]", 10}, 
          LegendMarkerSize -> {32, 12}], 
         LineLegend[{Blue, Black}, {"Theoretical line for data 1", 
          "Theoretical line for data 2"}, LegendMarkerSize -> {30, 12}]}, 
         Spacings -> 0];

Legended[Show[p1a, p2a], Placed[legend, {Scaled[.8], Scaled[.2]}]]

enter image description here

Alternatively, using the listplot as Epilog in Plot:

Plot[{curve1[x], curve2[x]}, {x, 0, 1}, 
 PlotRange -> {{0, 1}, {0, 0.8}}, PlotStyle -> {Blue, Black}, 
 Frame -> True, ImageSize -> Large, Epilog -> p1a[[1]], 
 PlotLegends ->  Placed[legend, {Scaled[.8], Scaled[.2]}]]

gives the same picture.

Note: Using the observation in @Virgil's answer, you could also use p1[[1]] and p2[[1]] in place of p1a and p2a, respectively. Similarly, Epilog->p1a[[1]] can be replaced with Epilog->p1[[1,1]].

$\endgroup$
4
  • $\begingroup$ Thanks for the answer, the update is very useful. Just a follow-up question about the update way. Without changing everything else (like the vertical spacing), can I enlarge the circle marker and thicken the line marker in the LineLegend? $\endgroup$
    – riorita
    Commented Apr 20, 2015 at 16:08
  • $\begingroup$ @user15908, something like mixedlegend = LineLegend[{White, White, Directive[Thick, Blue], Directive[Thick, Dashed, Black]}, {"Experimental data 1", "Experimental data 2", "Theoretical line for data 1", "Theoretical line for data 2"}, LegendMarkers -> {Graphics[{Red, Disk[]}], Graphics[{Orange, Disk[]}], None, None}, LegendMarkerSize -> Large]? $\endgroup$
    – kglr
    Commented Apr 20, 2015 at 16:21
  • $\begingroup$ @kguler LegendMarkerSize and Directive are what I need, thanks once again! $\endgroup$
    – riorita
    Commented Apr 20, 2015 at 16:30
  • $\begingroup$ @user15908, my pleasure. Glad it was useful for you. $\endgroup$
    – kglr
    Commented Apr 20, 2015 at 16:31
3
$\begingroup$

LegendMarkerSize is the key.

As an alternative to configuring the size manually, we can simply redraw a new combined legend with a single new legend using a single LegendMarkerSize. Although kguler's answer shows how to do this, I would like to point out here that it is possible to do this only using the two plots p1 and p2 supplied originally.

First note that a plot with a legend is a Legended object in Mathematica. It is also a tuple of two elements: the plot itself which is a Graphics object and a Placed legend.

Head@p1          (* -> Legended *)
Head@p1[[1]]     (* -> Graphics *)
Head@p1[[2]]     (* -> Placed *)
Head@p1[[2, 1]]  (* -> PointLegend *)

With a little trial and error, we can use this to break the two plots p1 and p2 up into components and use them to build a new legend we can use with the Legended function acting on a Show:

With[
 {
  plot1 = p1[[1]],
  plot2 = p2[[2]],
  legend1 = p1[[2, 1]],
  legend2 = p2[[2, 1]],
  place = p2[[2, 2]], (* position of new legend; good default *)
  lms = 15 (* legendmarkersize for new legend *)
 },
 Module[{points, lines, legends},
  points = MapThread[
    PointLegend[{#1}, {#2}, LegendMarkerSize -> lms] &, List@@legend1[[1 ;; 2]]];
  lines = MapThread[
    LineLegend[{#1}, {#2}, LegendMarkerSize -> lms] &, List@@legend2[[1 ;; 2]]];
  legends = points~Join~lines;
  Legended[Show[plot1, plot2], Placed[Column[legends], place]]
 ]
]

legended

In fact, this should be relatively easy to functionize (honestly, I'm not sure why Mathematica does't have something like this already - perhaps because the whole PlotLegends-type functionality is relatively new).

$\endgroup$
2
$\begingroup$

LegendMarkerSize is the key as Virgil said. Besides that, the legend system is smart enough to combine legends if they are placed at the same position. So, instead of specifying one legend at {0.8, 0.3} and one at {0.8, 0.2}, put them both at {0.8, 0.2} and then they will be combined automatically reasonably.

p1 = ListPlot[{list1, list2}, PlotRange -> {{0, 1}, {0, 0.8}}, 
   PlotStyle -> {{Red}, {Orange}}, Frame -> True, 
   PlotLegends -> 
    Placed[PointLegend[{"Experimental data 1", "Experimental data 2"},
       LegendMarkerSize -> {32, 12}], {0.8, 0.2}], ImageSize -> Large];
p2 = Plot[{curve1[x], curve2[x]}, {x, 0, 1}, 
   PlotRange -> {{0, 1}, {0, 0.8}}, PlotStyle -> {Blue, Black}, 
   Frame -> True, 
   PlotLegends -> 
    Placed[LineLegend[{"Theoretical line for data 1", 
       "Theoretical line for data 2"}, 
      LegendMarkerSize -> {32, 12}], {0.8, 0.2}], 
   ImageSize -> Large];
Show[p1, p2]

enter image description here

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