Matplotlib Tutorial: Legenden und Kommentare hinzufügen

Legend hinzufügen

Apollo and Diana slay the Python, Marcantonio Bassetti, 1618 - 1729

Wenn wir uns die Linien-Graphen der vorigen Beispiele anschauen dann merken wir, dass wir uns immer den Code anschauen müssen um zu verstehen, welche Art von Funktion nun dargestellt wird. Diese Information sollte zur Einfachheit direkt im Diagramm erscheinen. Dafür werden Legenden verwendet. Der Begriff stammt aus dem Lateinischen und steht für "das, was zu lesen ist". Also "muss es gelesen werden" um den Graphen zu verstehen.

Bevor Legenden in mathematischen Graphen verwendet wurden, wurden sie auf Karten verwendet. Legenden - wie sie auf Karten zu finden waren - haben die Bildsprache oder Symbolik auf der Karte erläutert. Auf Graphen erläutern sie die Funktion oder die Werte, die hinter den verschiedenen Linien des Graphen liegen.

Im folgenden demonstrieren wir ein einfaches Beispiel, wie eine Legend auf dem Graphen platziert werden kann. Eine Legende enthält einen oder mehrere Einträge. Jeder Eintrag besteht aus einem Schlüssel und einer Beschriftung.

Die pyplot-Funktion:

legend(*args, **kwargs)

platziert eine Legende auf den Achsen.

Alles was wir tun müssen um eine Legende für Linien zu erstellen, die bereits auf den Achsen existieren, ist der einfache Aufruf der Funktion "legend" mit einem iterierbaren Array aus Strings. Eins für jedes Element der Legende. Zum Beispiel:

In [1]:
# next line only needed if working with "ipython notebook":
%matplotlib inline

import numpy as np
import matplotlib.pyplot as plt

ax = plt.gca()

ax.plot([1, 2, 3, 4])
ax.legend(['A simple line'])
Out[1]:
<matplotlib.legend.Legend at 0x10bd85d30>

Wenn wir eine Beschriftung hinzufügen um die Funktion zu zeichnen (plotten), wird der Wert automatisch als Beschriftung im legend-Kommando verwendet. Das einzige Argument, welches die legend-Funktion braucht ist das Positions-Argument "loc":

In [2]:
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 25, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, '-b', label='sine')
plt.plot(x, y2, '-r', label='cosine')
plt.legend(loc='upper left')
plt.ylim(-1.5, 2.0)
plt.show()
In [3]:
import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(0, 25, 1000)

F1 = np.sin(0.5 * X)
F2 = 3 * np.cos(0.8*X)

plt.plot(X, F1, label="$sin(0.5 * x)$")
plt.plot(X, F2, label="$3 sin(x)$")
plt.legend(loc='upper right')
Out[3]:
<matplotlib.legend.Legend at 0x10cbd0748>

In den meisten Fällen wissen man nicht wie das Ergebnis aussehen wird, bevor es nicht ausgegeben wurde. Möglicherweise würde die Legende einen wichtigen Teil der Linie überdecken. Wenn Sie nicht wissen, wie die Daten aussehen werden, können Sie "best" als Argument für "loc" verwenden. Matplotlib wird automatisch versuchen die bestmögliche Position für die Legende zu finden:

In [4]:
import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(0, 25, 1000)

F1 = np.sin(0.5 * X)
F2 = 3 * np.cos(0.8*X)

plt.plot(X, F1, label="$sin(0.5 * x)$")
plt.plot(X, F2, label="$3 sin(x)$")
plt.legend(loc='best')
Out[4]:
<matplotlib.legend.Legend at 0x10ceb0eb8>
Im folgenden Beispiel kann man sehen, dass
loc='best'

sehr gut funktioniert:

In [5]:
import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(-2 * np.pi, 2 * np.pi, 70, endpoint=True)
F1 = np.sin(0.5*X)
F2 = -3 * np.cos(0.8*X)

plt.xticks( [-6.28, -3.14, 3.14, 6.28],
        [r'$-2\pi$', r'$-\pi$', r'$+\pi$', r'$+2\pi$'])
plt.yticks([-3, -1, 0, +1, 3])
plt.plot(X, F1, label="$sin(0.5x)$")
plt.plot(X, F2, label="$-3 cos(0.8x)$")
plt.legend(loc='best')

plt.show()
In [6]:
import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(-2 * np.pi, 2 * np.pi, 70, endpoint=True)
F1 = np.sin(0.5*X)
F2 = 3 * np.cos(0.8*X)

plt.xticks( [-6.28, -3.14, 3.14, 6.28],
        [r'$-2\pi$', r'$-\pi$', r'$+\pi$', r'$+2\pi$'])
plt.yticks([-3, -1, 0, +1, 3])
plt.plot(X, F1, label="$sin(0.5x)$")
plt.plot(X, F2, label="$3 cos(0.8x)$")
plt.legend(loc='best')

plt.show()



Kommentare

Natürlich hat die Sinus-Funktion "langweilige" und interessante Werte. Wir nehmen an, dass uns speziell der Wert von \(3 * sin(3 * pi/4)\) interessiert.

In [7]:
import numpy as np

print(3 * np.sin(3 * np.pi/4))
2.12132034356

Der Zahlenwert sieht nicht sehr speziell aus. Wenn wir aber eine symbolische Berechnung durchführen resultiert daraus \(\frac{3}{\sqrt{2}}\). Jetzt möchten wir genau diesen Punkt auf dem Graph markieren. Dies erreichen wir mit der Funktion "annotate".

In [7]:
import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(-2 * np.pi, 3 * np.pi, 70, endpoint=True)
F1 = np.sin(X)
F2 = 3 * np.sin(X)
ax = plt.gca()

plt.xticks( [-6.28, -3.14, 3.14, 6.28],
        [r'$-2\pi$', r'$-\pi$', r'$+\pi$', r'$+2\pi$'])
plt.yticks([-3, -1, 0, +1, 3])

x = 3 * np.pi / 4

plt.scatter([x,],[3 * np.sin(x),], 50, color ='blue')

plt.annotate(r'$(3\sin(\frac{3\pi}{4}),\frac{3}{\sqrt{2}})$',
         xy=(x, 3 * np.sin(x)), 
         xycoords='data',
         xytext=(+20, +20), 
         textcoords='offset points', 
         fontsize=16,
         arrowprops=dict(facecolor='blue'))

plt.plot(X, F1, label="$sin(x)$")
plt.plot(X, F2, label="$3 sin(x)$")
plt.legend(loc='lower left')

plt.show()

Wir müssen dafür einige Informationen für die annotate-Funktion als Parameter bereitstellen.

Parameter Bedeutung
xy Koordinaten der Pfeilspitze
xytext Koordinaten der Text-Position

Die xy- und xytext-Positionen sind in unserem Beispiel in den Daten-Koordinaten enthalten. Es gibt weitere Koordinaten-Systeme aus denen wir wählen können. Das Koordinaten-System von xy und xytext kann über String-Werte mit xycoords und textcoords spezifiziert werden. Der Default-Wert ist "data":

String-Wert Koordinaten-System
figure points Punkte von der linken unteren Ecke der Abbildung
figure pixels Pixel von der linken unteren Ecke der Abbildung
figure fraction 0,0 ist links unten und 1,1 ist rechts oben in der Abbildung
axes points Punkte von der linken unteren Ecke der Achsen
axes pixels Pixel von der linken unteren Ecke der Achsen
axes fraction 0,0 ist links unten und 1,1 ist rechts oben
data Verwende das Achsen-Daten-Koordinaten-System

Zusätzlich können die Eigenschaften des Pfeils spzifiziert werden. Dafür müssen wir ein Dictionary mit Pfeil-Eigenschaften als Parameter "arrowprops" bereitstellen:

arrowprops Schlüssel Beschreibung
width Die Breite des Pfeils in Punkten
headlength Der Teil, der vom Pfeilkopf eingenommen wird
(Anmerkung: frac wird nicht mehr unterstützt)
headwidth Die Breite der Pfeilspitzen-Basis in Punkten
shrink Verschiebe die Spitze und Basis um ein paar Prozent vom Kommentar-Punkt und -Text
**kwargs ein Schlüssel für matplotlib.patches.Polygon, z.B. facecolor

Im folgenden Beispiel verändern wir das Erscheinungsbild des Pfeils aus unserem vorigen Beispiel:

In [12]:
import numpy as np
import matplotlib.pyplot as plt

X = np.linspace(-2 * np.pi, 3 * np.pi, 70, endpoint=True)
F1 = np.sin(X)
F2 = 3 * np.sin(X)
ax = plt.gca()

plt.xticks( [-6.28, -3.14, 3.14, 6.28],
        [r'$-2\pi$', r'$-\pi$', r'$+\pi$', r'$+2\pi$'])
plt.yticks([-3, -1, 0, +1, 3])

x = 3 * np.pi / 4

plt.scatter([x,],[3 * np.sin(x),], 50, color ='blue')

plt.annotate(r'$(3\sin(\frac{3\pi}{4}),\frac{3}{\sqrt{2}})$',
         xy=(x, 3 * np.sin(x)), 
         xycoords='data',
         xytext=(+20, +20), 
         textcoords='offset points', 
         fontsize=16,
         arrowprops=dict(facecolor='blue', headwidth=15, headlength=5, width=2))

plt.plot(X, F1, label="$sin(x)$")
plt.plot(X, F2, label="$3 sin(x)$")
plt.legend(loc='lower left')

plt.show()
In [9]: