Charles Brunet Charles Brunet - 21 days ago 6
Python Question

matplotlib: 2 different legends on same graph

I have a plot where different colors are used for different parameters, and where different line styles are used for different algorithms. The goal is to compare the results of the different algorithms performed with similar parameters. It means in total I use 4 different colors, and 3 different line styles, for a total of 12 plots on the same graph.

I actually build the legend based on colors, associating each color with the corresponding parameter. Now I'd like to display a second legend on the same graph, with the meaning of each line style. It is possible to achieve that? How?

Here is what my code looks like actually:

colors = ['b', 'r', 'g', 'c']
cc = cycle(c)
for p in parameters:

d1 = algo1(p)
d2 = algo2(p)
d3 = algo3(p)

pyplot.hold(True)
c = next(cc)
pyplot.plot(d1, '-', color=c, label="d1")
pyplot.plot(d1, '--', color=c)
pyplot.plot(d2, '.-', color=c)

pyplot.legend()

Answer

There's a section in the matplotlib documentation on that exact subject: http://matplotlib.org/users/legend_guide.html#multiple-legends-on-the-same-axes

Here's code for your specific example:

import itertools
from matplotlib import pyplot

colors = ['b', 'r', 'g', 'c']
cc = itertools.cycle(colors)
plot_lines = []
for p in parameters:

    d1 = algo1(p)
    d2 = algo2(p)
    d3 = algo3(p)

    pyplot.hold(True)
    c = next(cc)
    l1, = pyplot.plot(d1, '-', color=c)
    l2, = pyplot.plot(d2, '--', color=c)
    l3, = pyplot.plot(d3, '.-', color=c)

    plot_lines.append([l1, l2, l3])

legend1 = pyplot.legend(plot_lines[0], ["algo1", "algo2", "algo3"], loc=1)
pyplot.legend([l[0] for l in plot_lines], parameters, loc=4)
pyplot.gca().add_artist(legend1)

Here's an example of its output: Plot with 2 legends, per-param and per-algo