matplotlib: 2 légendes différentes sur un même graphique

j'ai un graphique où différentes couleurs sont utilisées pour différents paramètres, et où différents styles de ligne sont utilisés pour différents algorithmes. L'objectif est de comparer les résultats des différents algorithmes réalisée avec des paramètres similaires. Cela signifie au total que j'utilise 4 couleurs différentes, et 3 styles de ligne différents, pour un total de 12 tracés sur le même graphique.

je construis en fait la légende basée sur les couleurs, en associant chaque couleur avec le paramètre correspondant. Maintenant, je voudrais afficher une deuxième légende sur le même graphique, avec la signification de chaque ligne de style. Il est possible d'y parvenir? Comment?

voici à quoi ressemble en fait mon code:

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()
46
demandé sur Charles Brunet 2012-10-06 20:55:30

2 réponses

Il y a une section dans la documentation de matplotlib sur ce sujet précis: http://matplotlib.org/users/legend_guide.html#multiple-legends-on-the-same-axes

Voici le code pour votre exemple:

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)

Voici un exemple de sa sortie: Plot with 2 legends, per-param and per-algo

60
répondu Mu Mind 2016-11-18 03:12:07

voici aussi une façon plus "pratique" de le faire (c.-à-d. interagir explicitement avec n'importe quel axe de la figure):

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)

j'aime cette façon de l'écrire car elle permet potentiellement de jouer avec différents axes d'une manière moins obscure. Vous pouvez d'abord créer votre jeu de légendes, puis les ajouter à la axes que vous voulez avec la méthode "add_artist". Aussi, je commence avec matplotlib, et pour moi au moins il est plus facile de comprendre les scripts quand les objets sont explicités.

NB: Be attention, vos légendes peuvent être coupées lors de l'affichage/sauvegarde. Pour résoudre ce problème, utilisez la méthode axes.set_position ([left, bottom, width, length]) pour rétrécir la sous-parcelle relativement à la taille de la figure et faire apparaître les légendes.

7
répondu Maxime Beau 2017-06-22 14:17:59