2

I have the following code to generate the plots with a shared legend

from matplotlib.legend_handler import HandlerLine2D, HandlerTuple
import matplotlib.pyplot as pt

fig = pt.figure(figsize = (12,4))
gd = fig.add_gridspec(1,2)
p1 = fig.add_subplot(gd[0])
p2 = fig.add_subplot(gd[1])

redLine, = p1.plot([1,2,3], [4,2,5], 'r-')
greenLine, = p1.plot([1,2,3], [8,9,1], 'g--')

redDot, = p2.plot([1,2,3], [4,2,5], 'ro')
greenDot, = p2.plot([1,2,3], [8,9,1], 'gs')

leg = p2.legend([(redLine, redDot), (greenLine, greenDot)], ['Red', 'Green'], handler_map = {tuple: HandlerTuple(ndivide=None)})

enter image description here

Doing this however makes the legend lines a bit too short to clearly differentiate between solid line and dashed, so I'm trying to figure out how to make them longer without making the entire legend bigger.

From the documentation here https://matplotlib.org/stable/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D, it seems I should be able to do this by setting the sketch_params property. I have the following

legLines = leg.get_lines()
pt.setp(legLines, sketch_params = (1,2,3))

but this tells me it must be real number, not tuple -- contrary to what the documentation suggests. Also note the numbers in this example are arbitrary since I was just trying to understand how to use this.

I've tried a bunch of different stuff to get this shared legend to happen, and this is by far the closest I've gotten. So I was just hoping someone could help explain how I'm misusing the sketch_params attribute, since it sounds like I should be able to specify the length with that.

EDIT: It was mentioned in the comments that to get sketch_params to work, I can simply do

for line in legLines:
    line.set_sketch_params(1,2,3)

But it turns out that doesn't actually let me change the length of the lines like I wanted to. So I changed the question for more general help on how to achieve that.

Bebotron
  • 383
  • 2
  • 11
  • Not sure how to set it with `setp`, but you can use the setter directly: `for line in legLines: line.set_sketch_params(1,2,3)` – tdy Mar 26 '21 at 02:41
  • Ok so that does accept the tuple the way I wanted, but it looks like I misunderstood what sketch_params did, since it doesn't look like it's making the lines longer like I intended. Perhaps I need to rephrase the question – Bebotron Mar 26 '21 at 03:43
  • `p2.legend([(redLine, redDot), (greenLine, greenLine, greenDot)],...)` If you do this, you will have a series of dotted lines. Is this not good enough? – r-beginners Mar 26 '21 at 04:48
  • 1
    This is a really nice workaround that works for my purposes. It does make the red and green markers misalign, but that doesn't matter much to me. Ultimately it would be nice to know if there is a way to do what I initially intended, since I could be using this for multiple data sets with different line styles, for which a longer legend line will be needed. For this small working example it's fine though. – Bebotron Mar 26 '21 at 17:56
  • I started dipping my toes in doing it manually until I found the method above, which was very compact and easy to reproduce. Maybe I'll have to go back to drawing manually though :/ – Bebotron Mar 26 '21 at 22:49

1 Answers1

5

Sorry for the noise, turns out the answer is quite simple, and I found it on this post How to adjust the size of matplotlib legend box? and Matplotlib: Horizontal Linelength in Legend. Just need to use the handlelength keyword. Apologies, I wasn't phrasing the question correctly when looking for it. Marking this as duplicate.

Bebotron
  • 383
  • 2
  • 11
  • It's likely that others will make a similar error in terminology. Nice question. Glad you found the answer. – Mad Physicist Mar 26 '21 at 23:06
  • Thanks, I figured I wouldn't delete in case someone might find it useful even if for the links to other posts. Figured I'd let the community decide what to do with it. – Bebotron Mar 26 '21 at 23:15