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()
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.
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.
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.
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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With