matplotlib: 2 verschiedene Legenden in derselben Grafik

72

Ich habe ein Diagramm, in dem verschiedene Farben für verschiedene Parameter verwendet werden und in dem verschiedene Linienstile für verschiedene Algorithmen verwendet werden. Ziel ist es, die Ergebnisse der verschiedenen Algorithmen mit ähnlichen Parametern zu vergleichen. Insgesamt verwende ich 4 verschiedene Farben und 3 verschiedene Linienstile für insgesamt 12 Diagramme im selben Diagramm.

Ich baue die Legende tatsächlich basierend auf Farben und ordne jede Farbe dem entsprechenden Parameter zu. Jetzt möchte ich eine zweite Legende im selben Diagramm mit der Bedeutung jedes Linienstils anzeigen. Ist es möglich das zu erreichen? Wie?

So sieht mein Code tatsächlich aus:

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()
Charles Brunet
quelle

Antworten:

97

Zu diesem Thema gibt es einen Abschnitt in der matplotlib-Dokumentation: http://matplotlib.org/users/legend_guide.html#multiple-legends-on-the-same-axes

Hier ist Code für Ihr spezielles Beispiel:

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)

Hier ist ein Beispiel für die Ausgabe: Handlung mit 2 Legenden, pro Parameter und pro Algo

Mu Mind
quelle
11
Der Schlüssel ist also in add_artist... aus irgendeinem verrückten Grund entscheidet matplotlib, dass es besser weiß und löscht die ursprüngliche Legende, dann müssen Sie sie später wieder hinzufügen. Danke für die Hilfe, ich werde ein Bier trinken.
Luke Davis
17

Hier ist auch eine "praktischere" Möglichkeit, dies zu tun (dh explizite Interaktion mit beliebigen Figurenachsen):

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)

Ich mag diese Art des Schreibens, da es möglicherweise erlaubt, auf weniger dunkle Weise mit verschiedenen Achsen zu spielen. Sie können zuerst Ihre Legenden erstellen und sie dann mit der Methode "add_artist" zu den gewünschten Achsen hinzufügen. Außerdem beginne ich mit matplotlib, und für mich ist es zumindest einfacher, Skripte zu verstehen, wenn Objekte explizit angegeben werden.

NB: Seien Sie vorsichtig, Ihre Legenden können beim Anzeigen / Speichern abgeschnitten sein. Um dieses Problem zu lösen, verwenden Sie die Methode axes.set_position ([links, unten, Breite, Länge]), um das Unterplot relativ zur Figurengröße zu verkleinern und die Legenden erscheinen zu lassen.

Maxime Beau
quelle
1

Sie können auch verwenden line.get_label()

import matplotlib.pyplot as plt

plt.figure()

colors = ['b', 'r', 'g', 'c']
parameters = [1,2,3,4]
for p in parameters:

  color = colors[parameters.index(p)]
  plt.plot([1,10],[1,p], '-', c=color, label='auto label '+str(p))

lines = plt.gca().get_lines()
include = [0,1]
legend1 = plt.legend([lines[i] for i in include],[lines[i].get_label() for i in include], loc=1)
legend2 = plt.legend([lines[i] for i in [2,3]],['manual label 3','manual label 4'], loc=4)
plt.gca().add_artist(legend1)
plt.show()

Automatische und manuelle Beschriftungen

Paul Chen
quelle
1

Was ist mit einer Doppelgeisterachse?

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()

colors = ['b', 'r', 'g', ]
styles = ['-', '--', '-.']

for cc, col in enumerate(colors):
    for ss, sty in enumerate(styles):
        print(cc, ss)
        ax.plot([0, 1], [cc, ss], c=colors[cc], ls=styles[ss])

for cc, col in enumerate(colors):
    ax.plot(np.NaN, np.NaN, c=colors[cc], label=col)

ax2 = ax.twinx()
for ss, sty in enumerate(styles):
    ax2.plot(np.NaN, np.NaN, ls=styles[ss],
             label='style ' + str(ss), c='black')
ax2.get_yaxis().set_visible(False)

ax.legend(loc=1)
ax2.legend(loc=3)

plt.show()

Geben Sie hier die Bildbeschreibung ein

Tojur
quelle