Objektorientiertes Interface#

Mit dem funktionalen Interface haben wir eine einfache und schnelle Variante des Plottens mit Matplotlib kennengelernt. Diese Form der Verwendungform von Matplotlib reicht in vielen Fällen aus, um einfache Graphiken zu erstellen. Dennoch stößt dieser Ansatz an seine Grenzen, möchte man die “volle Kontrolle” beim Erstellen von Diagrammen haben. Und vor allem, wenn man fortgeschrittene Techniken wie die Animation von Diagrammen anwenden möchte, dann müssen wir die nun vorgestellte objektorientierte Form der Anwendung von Matplotlib verwenden.

Während man bei der funktionalen Bedinung von Matplotlib vor allem verschiedene Funktionen verwendet hat, arbeitet man in der objektorientierten Bedinung vor allem mit den Objekten, aus denen die Diagramme zusammengesetzt werden, sowie ihren Methoden. Denn jedes Diagramm besteht in Matplotlib aus mehreren Einzelteilen, welche wir z.B. bei der Verwendung von plt.plot() ohne es zu merken im Hintergrund erstellt haben. Wir erstellen diese ab jetzt selbst.

Die grundlegenden Bestandteile eines Diagramms in Matplotlib sind das sogenannte Figure-Objekt und das sogenannte Axes-Objekt.

Eine Figure-Objekt ist das Fenster, in das ein oder mehrere Diagramme eingezeichnet werden. Es ist praktisch eine leere Leinwand, auf die prinzipiell gezeichnet werden kann. Jedes Diagramm muss auf ein Figure-Objekt gezeichnet werden. Ein leeres Figure-Objekt sieht wie unten im Screenshot aus. Auf die große weiße Fläche könnten dort alle möglichen Diagramme eingezeichnet werden.

Das Axes-Objekt ist mehr oder weniger das Diagramm selbst. Genaugenommen ist es ein abegrenzter “Diagrammbereich” auf einem Figure-Objekt, in den Datenpunkte in Relation zu einer bestimmten Achsen-Skalierungen eingezeichnet werden können. Während das Figure-Objekt also die leere Leinwand ist, auf die prinzipiell etwas gezeichnet werden kann, ist das Axes-Objekt ein Koordinatensystem auf dieser leeren Leinwand, in die Datenpunkte in Relation zu einem Koordinatensystem eingezeichnet werden können. Ein Axes-Objekt muss immer auf einem Figure-Objekt gezeichnet werden. Ein Figure-Objekt kann mehrere Axes beinhalten.

In ein Figure-Objekt können prinzipiell beliebig viele, beliebig große Axes-Objekte an beliebigen Positionen eingefügt werden.

Wie erstellt man nun solche Figure- und Axes-Objekte? Der ursprünglich einmal von Matplotlib erdachte Weg um diese Objekte hat sich im Verlauf der Zeit als etwas unnötig kompliziert herausgestellt. Dabei erstellt man z.B. ein Figure-Objekt mit dem Befehl plt.Figure(), wobei man mit dem dadurch erstellten Objekt dann weiterarbeitet und z.B. mit der Figure-Methode .add_axes() die Axes-Objekte erstellt. Tatsächlich sieht man dieses Vorgehen aber äußerst selten. Im Folgenden schauen wir uns an, wie man stattdessen in der Regel die benötigten Objekte erstellt und mit diesen das Diagramm erstellt.

Axes und Figures mit plt.subplots() erstellen#

Die Funktion plt.subplots() ermöglicht es, gleichzeitig ein Figure-Objekt sowie ein oder mehrere Axes-Objekte gleichzeitig zu erstellen. Im einfachsten Fall - ohne irgendeineinen weiteren Input - gibt die Funktion plt.subplots() genau ein Figure-Objekt und genau ein Axes-Objekt zurück. Ruft man die Funktion plt.subplots() z.B. in der Spyder-Konsole auf, dann gibt diese einen Tupel (das ist so etwas wie eine Liste), welcher das Figure- und das Axes-Objekt enthält, aus. Das sieht in dann ungefähr so aus:

(<Figure size 432x288 with 1 Axes>,  <matplotlib.axes._subplots.AxesSubplot at 0x2a7520de848>)

Das erste Objekt im obigen Tupel ist das Figure-Objekt, das zweite Objekt ist ein Axes-Objekt. Wir könnten nun theoretisch auch das gesamte Tupel einer einzigen Variable zuweisen, ohne die darin entahltenen Objekte zu entpacken. Das wäre aber für die weitere Arbeit mit den Objekten bei der Diagrammerstellung recht unpraktisch, da wir dann per Indizierung jeweils auf die einzelnen Objekte zugreifen müssten. Daher wenden wir hier besser die Mehrfachzuweisung an und weisen das Figure-Objekt und das Axes-Objekt direkt jeweils einem eigenen Variablennamen zu. Ich verwende hier zu Demonstrationszwecken die Variablennamen leinwand (Figure) und diagrammbereich (Axes). Natürlich kann man auch kürzere Namen wählen. Es hat sich eingebürgert ein Figure-Objekt unter dem Namen fig und ein Axes-Objekt unter dem Namen ax abzuspeichern.

import matplotlib.pyplot as plt

leinwand, diagrammbereich = plt.subplots()
../_images/amp06a_04_objektorientiertes_matplotlib_8_0.png

Nachdem das Figure-Objekt und das Axes-Objekt auf diese Weise erstellt und abgespeichert wurde, können Datenpunkte innerhalb des erstellten Axes-Objektes eingezeichnet werden. Dabei nehmen wir das Axes-Objekt diagrammbereich und führen dessen Methode .plot() aus. Diese Methode funktioniert dabei an sich genau wie die Funktion plt.plot(). Der Unterschied ist nun, dass wir ganz gezielt das eine bestimmte Axes-Objekt anwählen und in dieses die Datenpunkte mittels der eigenen Methode .plot() einzeichnen. Das ist v.a. praktisch, wenn wir auf ein Figure-Objekt d.h. auf eine Leinwand mehrere Diagramme bzw. Diagrammbereiche auftragen wollen.

# Fiktive Daten erstellen
x_data = [1, 2, 3, 4, 5]
y_data = [1, 2, 4, 8, 16]

# Figure und Axes erstellen
leinwand, diagrammbereich = plt.subplots()

# in den Diagrammbereich die Daten einzeichnen
diagrammbereich.plot(x_data, y_data)

# Diagramm anzeigen
plt.show()
../_images/amp06a_04_objektorientiertes_matplotlib_10_0.png

Übrigens

Einer der großen Vorteile der objektorientierten Verwendung von Matplotlib und der Funktion plt.subplots() ist, dass dadurch relativ einfach mehrere Diagramme bzw. Diagrammbereiche in ein und dasselbe Figure-Objekt eingezeichnet werden können. Das brauchen wir in diesem Kurs nicht unbedingt, kann aber relativ praktisch sein. Falls du daran interessiert bist, wie das funktioniert, schau doch mal hier. Wir nutzen das objektorientierte Interface von Matplotlib in diesem Kurs vorrangig, weil man dieses für die Erstellung von Animationen benötigt.

Diagramme aufhübschen#

Auch im objektorientierten Interface von Matplotlib können wir natürlich die Diagramme noch etwas schicker und leserlicher machen. Einiges ist dabei ähnlich, anderes ist etwas anders im Vergleich zum funktionalen Interface.

Wichtig: Alle Beispiele erfolgen anhand eines Figure-Objektes mit einem Axes-Objekt. Sind mehrere Axes-Objekte auf einem Figure-Objekt vorhanden, muss dementsprechend der Axes-spezifische Code auf die jeweiligen Axes-Objekte angepasst werden.

Diagramm-Titel und Achsen-Label#

Wichtig für die Lesbarkeit von Diagrammen ist deren Betitelung und die Beschriftung der Achsen. Um diese hinzuzufügen, kann die Axes-Methode set() ausgeführt werden und den Parametern title, xlabel und ylabel die gewünschten Werte zugewiesen werden.

Unten erstelle ich zunächst wieder Beispieldaten, erstelle ein Figure- und ein Axes-Objekt, plotte die Daten und füge dann schließlich die Beschriftungen hinzu.

# Daten erstellen
days = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
infections = [1, 2, 3, 5, 8, 13, 21, 26, 29, 31, 32, 32, 31, 29, 26, 21, 13, 8, 5, 3]

# Figure- und Axes-Objekt erstellen
leinwand, diagrammbereich = plt.subplots()

# Daten einzeichnen
diagrammbereich.plot(days, infections)

# Diagramm-Titel und Achen-Label einfügen
diagrammbereich.set(xlabel="Tage", ylabel="Infektionen", title = "Verlauf Pandemie")

# Diagramm anzeigen
plt.show()
../_images/amp06a_04_objektorientiertes_matplotlib_13_0.png

Achsenbereiche festlegen#

Manchmal kann es notwendig sein, den angezeigten Bereich der X- und Y-Achsen selbst zu bestimmen. Auch dies geht innerhalb der Methode set(). Die Parameter xlim und ylim nehmen eine Liste, welche das jeweilige Achsenminimum und das Achsenmaximum enthält, entgegen. Zur besseren Übersicht schreibe ich unten die Paramter der Methode set() untereinander.

# Daten erstellen
days = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
infections = [1, 2, 3, 5, 8, 13, 21, 26, 29, 31, 32, 32, 31, 29, 26, 21, 13, 8, 5, 3]

# Figure- und Axes-Objekt erstellen
leinwand, diagrammbereich = plt.subplots()

# Daten einzeichnen
diagrammbereich.plot(days, infections)

# Diagramm-Titel und Achen-Label einfügen
diagrammbereich.set(
    xlabel="Tage", 
    ylabel="Infektionen", 
    title = "Verlauf Pandemie",
    xlim = [0, 30],
    ylim = [0, 50],    
)

# Diagramm anzeigen
plt.show()
../_images/amp06a_04_objektorientiertes_matplotlib_15_0.png

Linienbeschriftung und Legende#

Wenn man mehrere Datenreihen in ein Diagramm bzw. ein Axes-Objekt einzeichnen möchte, dann empfiehlt es sich auch hier die einzelnen Datenreihen zu bezeichnen und dann deren Bezeichnung in einer Legende anzuzeigen. Dafür kann in der Methode, mit welcher die Daten gezeichnet werden - in diesem Fall plot() - der Parameter label genutzt werden, um die gerade gezeichnete Datenreihe zu bezeichnen. Unten geschieht dies in den Zeilen 10 und 11. Schließlich muss noch die Legende angezeigt werden. Dies geschieht über die Axes-Methode legend() in Zeile 17.

# Daten erstellen
days = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
infections = [1, 2, 3, 5, 8, 13, 21, 26, 29, 31, 32, 32, 31, 29, 26, 21, 13, 8, 5, 3]
recoveries = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 5, 8, 13, 21, 26, 29, 31, 32]

# Figure- und Axes-Objekt erstellen
leinwand, diagrammbereich = plt.subplots()

# Daten einzeichnen (mit Label)
diagrammbereich.plot(days, infections, label = "Infizierte")
diagrammbereich.plot(days, recoveries, label = "Geheilte")

# Diagramm-Titel und Achen-Label einfügen
diagrammbereich.set(xlabel="Tage", ylabel="Infektionen", title = "Verlauf Pandemie")

# Legende einzeichnen
diagrammbereich.legend()

# Diagramm anzeigen
plt.show()
../_images/amp06a_04_objektorientiertes_matplotlib_17_0.png

Gitter anzeigen#

Um ein Gitter im Hintergrund des Plots anzuzeigen, kann die Axes-Methode grid() aufgerufen werden.

# Daten erstellen
days = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
infections = [1, 2, 3, 5, 8, 13, 21, 26, 29, 31, 32, 32, 31, 29, 26, 21, 13, 8, 5, 3]
recoveries = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 5, 8, 13, 21, 26, 29, 31, 32]

# Figure- und Axes-Objekt erstellen
leinwand, diagrammbereich = plt.subplots()

# Daten einzeichnen
diagrammbereich.plot(days, infections, label = "Infizierte")
diagrammbereich.plot(days, recoveries, label = "Geheilte")

# Diagramm-Titel und Achen-Label einfügen
diagrammbereich.set(xlabel="Tage", ylabel="Infektionen", title = "Verlauf Pandemie")

# Legende einzeichnen
diagrammbereich.legend()

# Gitter einzeichnen
diagrammbereich.grid()

# Diagramm anzeigen
plt.show()
../_images/amp06a_04_objektorientiertes_matplotlib_19_0.png

Größe festlegen#

Möchte man die Größe des erstellten Fensters, also dem Figure-Objekt, per Programmierung bestimmen, kann man die Methode set_size_inches() verwenden. Die Methode erwartet zwei Zahlen, welche die Höhe und Breite des Figure-Objektes in der Einheit Inch festlegen.

from matplotlib import pyplot as plt

# Daten erstellen
days = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
infections = [1, 2, 3, 5, 8, 13, 21, 26, 29, 31, 32, 32, 31, 29, 26, 21, 13, 8, 5, 3]
recoveries = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 5, 8, 13, 21, 26, 29, 31, 32]

# Figure- und Axes-Objekt erstellen
leinwand, diagrammbereich = plt.subplots()

# Größe des Figure-Objektes verändern
leinwand.set_size_inches(10,10)

# Daten einzeichnen
diagrammbereich.plot(days, infections, label = "Infizierte")
diagrammbereich.plot(days, recoveries, label = "Geheilte")

# Diagramm-Titel und Achen-Label einfügen
diagrammbereich.set(
    xlabel="Tage", 
    ylabel="Infektionen", 
    title = "Verlauf Pandemie",  
)

# Legende einzeichnen
diagrammbereich.legend()

# Gitter einzeichnen
diagrammbereich.grid()

# Diagramm anzeigen
plt.show()
../_images/amp06a_04_objektorientiertes_matplotlib_21_0.png