Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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() 
like image 936
Charles Brunet Avatar asked Oct 06 '12 16:10

Charles Brunet


People also ask

Can I have two legends in Matplotlib?

Multiple Legends. Sometimes when designing a plot you'd like to add multiple legends to the same axes. Unfortunately, Matplotlib does not make this easy: via the standard legend interface, it is only possible to create a single legend for the entire plot. If you try to create a second legend using plt.

How do I show multiple legends in Matplotlib?

Place the first legend at the upper-right location. Add artist, i.e., first legend on the current axis. Place the second legend on the current axis at the lower-right location. To display the figure, use show() method.

Can you have two legends?

You will need to have two plots per line (with each plot using one property) if you need two legends. Then add the legend for the first property by only using the lines that are representative of the first property. You can then use the 'copyobj' function to copy the legend and its axis.


2 Answers

There's a section in the matplotlib documentation on that exact subject.

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

like image 199
Mu Mind Avatar answered Oct 13 '22 04:10

Mu Mind


Here is also a more "hands-on" way to do it (i.e. interacting explicitely with any figure axes):

import itertools from matplotlib import pyplot  fig, axes = plt.subplot(1,1)  colors = ['b', 'r', 'g', 'c'] cc = itertools.cycle(colors) plot_lines = [] for p in parameters:      d1 = algo1(p)     d2 = algo2(p)     d3 = algo3(p)      c = next(cc)     axes.plot(d1, '-', color=c)     axes.plot(d2, '--', color=c)     axes.plot(d3, '.-', color=c)  # In total 3x3 lines have been plotted lines = axes.get_lines() legend1 = pyplot.legend([lines[i] for i in [0,1,2]], ["algo1", "algo2", "algo3"], loc=1) legend2 = pyplot.legend([lines[i] for i in [0,3,6]], parameters, loc=4) axes.add_artist(legend1) axes.add_artist(legend2) 

I like this way of writing it since it allows potentially to play with different axes in a less obscure way. You can first create your set of legends, and then add them to the axes you want with the method "add_artist". Also, I am starting with matplotlib, and for me at least it is easier to understand scripts when objets are explicited.

NB: Be careful, your legends may be cutoff while displaying/saving. To solve this issue, use the method axes.set_position([left, bottom, width, length]) to shrink the subplot relatively to the figure size and make the legends appear.

like image 34
Maxime Beau Avatar answered Oct 13 '22 05:10

Maxime Beau