matplotlib

Table Of Contents

Previous topic

Customizing Location of Subplot Using GridSpec

Next topic

Event handling and picking

This Page

Legend guide

Do not proceed unless you already have read legend() and matplotlib.legend.Legend!

What to be displayed

The legend command has a following call signature:

legend(*args, **kwargs)

If len(args) is 2, the first argument should be a list of artist to be labeled, and the second argument should a list of string labels. If len(args) is 0, it automatically generate the legend from label properties of the child artists by calling get_legend_handles_labels() method. For example, ax.legend() is equivalent to:

handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)

The get_legend_handles_labels() method returns a tuple of two lists, i.e., list of artists and list of labels (python string). However, it does not return all of its child artists. It returns all artists in ax.lines and ax.patches and some artists in ax.collection which are instance of LineCollection or RegularPolyCollection. The label attributes (returned by get_label() method) of collected artists are used as text labels. If label attribute is empty string or starts with “_”, that artist will be ignored.

  • Note that not all kind of artists are supported by the legend. The following is the list of artists that are currently supported.

    Unfortunately, there is no easy workaround when you need legend for an artist not in the above list (You may use one of the supported artist as a proxy. See below), or customize it beyond what is supported by matplotlib.legend.Legend.

  • Remember that some pyplot commands return artist not supported by legend, e.g., fill_between() returns PolyCollection that is not supported. Or some return multiple artists. For example, plot() returns list of Line2D instances, and errorbar() returns a length 3 tuple of Line2D instances.

  • The legend does not care about the axes that given artists belongs, i.e., the artists may belong to other axes or even none.

Adjusting the Order of Legend items

When you want to customize the list of artists to be displayed in the legend, or their order of appearance. There are a two options. First, you can keep lists of artists and labels, and explicitly use these for the first two argument of the legend call.:

p1, = plot([1,2,3])
p2, = plot([3,2,1])
p3, = plot([2,3,1])
legend([p2, p1], ["line 2", "line 1"])

Or you may use get_legend_handles_labels() to retrieve list of artist and labels and manipulate them before feeding them to legend call.:

ax = subplot(1,1,1)
p1, = ax.plot([1,2,3], label="line 1")
p2, = ax.plot([3,2,1], label="line 2")
p3, = ax.plot([2,3,1], label="line 3")

handles, labels = ax.get_legend_handles_labels()

# reverse the order
ax.legend(handles[::-1], labels[::-1])

# or sort them by labels
import operator
hl = sorted(zip(handles, labels),
            key=operator.itemgetter(1))
handles2, labels2 = zip(*hl)

ax.legend(handles2, labels2)

Using Proxy Artist

When you want to display legend for an artist not supported by matplotlib, you may use another artist as a proxy. For example, you may create a proxy artist without adding it to the axes (so the proxy artist will not be drawn in the main axes) and feed it to the legend function.:

p = Rectangle((0, 0), 1, 1, fc="r")
legend([p], ["Red Rectangle"])

Multicolumn Legend

By specifying the keyword argument ncol, you can have a multi-column legend. Also, mode=”expand” horizontally expand the legend to fill the axes area. See legend_demo3.py for example.

Legend location

The location of the legend can be specified by the keyword argument loc, either by string or a integer number.

String Number
upper right 1
upper left 2
lower left 3
lower right 4
right 5
center left 6
center right 7
lower center 8
upper center 9
center 10

By default, the legend will anchor to the bbox of the axes (for legend) or the bbox of the figure (figlegend). You can specify your own bbox using bbox_to_anchor argument. bbox_to_anchor can be an instance of BboxBase, a tuple of 4 floats (x, y, width, height of the bbox), or a tuple of 2 floats (x, y with width=height=0). Unless bbox_transform argument is given, the coordinates (even for the bbox instance) are considered as normalized axes coordinates.

For example, if you want your axes legend located at the figure corner (instead of the axes corner):

l = legend(bbox_to_anchor=(0, 0, 1, 1), transform=gcf().transFigure)

Also, you can place above or outer right-hand side of the axes,

from matplotlib.pyplot import *

subplot(211)
plot([1,2,3], label="test1")
plot([3,2,1], label="test2")
legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
       ncol=2, mode="expand", borderaxespad=0.)

subplot(223)
plot([1,2,3], label="test1")
plot([3,2,1], label="test2")
legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)


show()

[source code, hires.png, pdf]

../_images/simple_legend01.png

Multiple Legend

Sometime, you want to split the legend into multiple ones.:

p1, = plot([1,2,3])
p2, = plot([3,2,1])
legend([p1], ["Test1"], loc=1)
legend([p2], ["Test2"], loc=4)

However, the above code only shows the second legend. When the legend command is called, a new legend instance is created and old ones are removed from the axes. Thus, you need to manually add the removed legend.

from matplotlib.pyplot import *

p1, = plot([1,2,3], label="test1")
p2, = plot([3,2,1], label="test2")

l1 = legend([p1], ["Label 1"], loc=1)
l2 = legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes.
gca().add_artist(l1) # add l1 as a separate artist to the axes

show()

[source code, hires.png, pdf]

../_images/simple_legend02.png