56

I am producing some plots in matplotlib and would like to add explanatory text for some of the data. I want to have a string inside my legend as a separate legend item above the '0-10' item. Does anyone know if there is a possible way to do this?

enter image description here

This is the code for my legend:
ax.legend(['0-10','10-100','100-500','500+'],loc='best')

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Osmond Bishop
  • 7,560
  • 14
  • 42
  • 51
  • If there isn't a proper way of doing this the only other option I can think of is to trick the graph into producing it by plotting some empty values – Osmond Bishop May 30 '13 at 02:06
  • Try `annotate()` function. I just asked similar question: http://stackoverflow.com/questions/16823703/adding-label-to-contour – theta May 30 '13 at 02:21
  • 7
    Why not simply set the legends `title`? I.e. `ax.legend(['0-10','10-100','100-500','500+'], loc='best', title='Explanatory text')`. – sodd May 31 '13 at 08:13

3 Answers3

115

Alternative solution, kind of dirty but pretty quick.

import pylab as plt

X = range(50)
Y = range(50)
plt.plot(X, Y, label="Very straight line")

# Create empty plot with blank marker containing the extra label
plt.plot([], [], ' ', label="Extra label on the legend")

plt.legend()
plt.show()

enter image description here

Clement H.
  • 1,339
  • 2
  • 8
  • 6
56

Sure. ax.legend() has a two argument form that accepts a list of objects (handles) and a list of strings (labels). Use a dummy object (aka a "proxy artist") for your extra string. I picked a matplotlib.patches.Rectangle with no fill and 0 linewdith below, but you could use any supported artist.

For example, let's say you have 4 bar objects (since you didn't post the code used to generate the graph, I can't reproduce it exactly).

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
fig = plt.figure()
ax = fig.add_subplot(111)
bar_0_10 = ax.bar(np.arange(0,10), np.arange(1,11), color="k")
bar_10_100 = ax.bar(np.arange(0,10), np.arange(30,40), bottom=np.arange(1,11), color="g")
# create blank rectangle
extra = Rectangle((0, 0), 1, 1, fc="w", fill=False, edgecolor='none', linewidth=0)
ax.legend([extra, bar_0_10, bar_10_100], ("My explanatory text", "0-10", "10-100"))
plt.show()

example output

Jeff Tratner
  • 16,270
  • 4
  • 47
  • 67
  • 2
    Thanks, this works. I'd also like to do this with a different plot that has a line plotted on top of the bars, but I get the following error c:\Python27\lib\site-packages\matplotlib\legend.py:628: UserWarning: Legend does not support [] Use proxy artist instead. – Osmond Bishop May 30 '13 at 21:58
  • 5
    it's actually a really common thing. I bet you've done something like: `line = ax.plot(x, y)`. The issue is that `plot` returns a *list* of lines, so you need to get at the actual artist. You can either do `line = ax.plot(x, y)[0]` or do `line, = ax.plot(x, y)` which takes advantage of parameter unpacking. – Jeff Tratner May 30 '13 at 22:21
  • It is better to set the rectangle transparent to fit with any background: `Rectangle((0, 0), 1, 1, alpha=0)` – Opsse Jun 09 '23 at 22:48
14

I found another way to do that just try:

plt.legend(title='abc xyz')

I used this in my work!

S.B
  • 13,077
  • 10
  • 22
  • 49
Do Minh Ha
  • 141
  • 1
  • 2
  • 4
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 03 '22 at 15:28
  • 2
    This should be marked as the correct answer; this does exactly what the OP wanted and is not hacky at all. – Ian Michael Williams Apr 12 '22 at 21:01