Matplotlib-Anwendungsschnittstellen (APIs) #

Matplotlib hat zwei Hauptanwendungsschnittstellen oder Arten der Verwendung der Bibliothek:

  • Eine explizite „Axes“-Schnittstelle, die Methoden auf einem Figure- oder Axes-Objekt verwendet, um andere Künstler zu erstellen und Schritt für Schritt eine Visualisierung zu erstellen. Dies wurde auch als "objektorientierte" Schnittstelle bezeichnet.

  • Eine implizite "Pyplot"-Schnittstelle, die die zuletzt erstellten Figuren und Achsen verfolgt und Künstler zu dem Objekt hinzufügt, von dem sie glaubt, dass der Benutzer es haben möchte.

Darüber hinaus bieten eine Reihe nachgelagerter Bibliotheken (wie pandasund xarray ) eine plotMethode an, die direkt in ihren Datenklassen implementiert ist, sodass Benutzer aufrufen können data.plot().

Der Unterschied zwischen diesen Schnittstellen kann etwas verwirrend sein, insbesondere angesichts von Snippets im Web, die die eine oder andere oder manchmal mehrere Schnittstellen im selben Beispiel verwenden. Hier versuchen wir aufzuzeigen, wie sich die „pyplot“- und Downstream-Schnittstellen auf die explizite „Axes“-Schnittstelle beziehen, um den Benutzern zu helfen, sich besser in der Bibliothek zurechtzufinden.

Native Matplotlib-Schnittstellen #

Die explizite "Achsen"-Schnittstelle #

Matplotlib wird über die Schnittstelle „Axes“ implementiert, und viele Anpassungen und Feinabstimmungen werden auf dieser Ebene vorgenommen.

Diese Schnittstelle funktioniert, indem sie eine Instanz einer FigureKlasse ( figunten) instanziiert, eine subplotsMethodenmethode (oder ähnliches) für dieses Objekt verwendet, um ein oder mehrere AxesObjekte ( axunten) zu erstellen, und dann Zeichenmethoden für die Achsen aufruft ( plotin diesem Beispiel):

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.subplots()
ax.plot([1, 2, 3, 4], [0, 0.5, 1, 0.2])

( Quellcode , png )

../../_images/api_interfaces-1.png

Wir nennen dies eine "explizite" Schnittstelle, weil jedes Objekt explizit referenziert und verwendet wird, um das nächste Objekt zu erstellen. Das Beibehalten von Verweisen auf die Objekte ist sehr flexibel und ermöglicht es uns, die Objekte anzupassen, nachdem sie erstellt wurden, aber bevor sie angezeigt werden.

Die implizite "pyplot"-Schnittstelle #

Das pyplotModul schattiert die meisten AxesZeichenmethoden, um das Äquivalent zu den oben genannten zu erhalten, wobei die Erstellung der Figur und der Achsen für den Benutzer erfolgt:

import matplotlib.pyplot as plt

plt.plot([1, 2, 3, 4], [0, 0.5, 1, 0.2])

( Quellcode , png )

../../_images/api_interfaces-2.png

Dies kann praktisch sein, insbesondere bei interaktiven Arbeiten oder einfachen Skripten. Ein Verweis auf die aktuelle Figur kann mit gcfund auf die aktuellen Achsen mit abgerufen werden gca. Das pyplotModul behält eine Liste von Figuren, und jede Figur behält eine Liste von Achsen auf der Figur für den Benutzer, so dass Folgendes gilt:

import matplotlib.pyplot as plt

plt.subplot(1, 2, 1)
plt.plot([1, 2, 3], [0, 0.5, 0.2])

plt.subplot(1, 2, 2)
plt.plot([3, 2, 1], [0, 0.5, 0.2])

( Quellcode , png )

../../_images/api_interfaces-3.png

ist äquivalent zu:

import matplotlib.pyplot as plt

plt.subplot(1, 2, 1)
ax = plt.gca()
ax.plot([1, 2, 3], [0, 0.5, 0.2])

plt.subplot(1, 2, 2)
ax = plt.gca()
ax.plot([3, 2, 1], [0, 0.5, 0.2])

( Quellcode , png )

../../_images/api_interfaces-4.png

In der expliziten Schnittstelle wäre dies:

import matplotlib.pyplot as plt

fig, axs = plt.subplots(1, 2)
axs[0].plot([1, 2, 3], [0, 0.5, 0.2])
axs[1].plot([3, 2, 1], [0, 0.5, 0.2])

( Quellcode , png )

../../_images/api_interfaces-5.png

Warum explizit sein? #

Was passiert, wenn Sie zurückgehen und auf einer alten Achse arbeiten müssen, die nicht von referenziert wird plt.gca()? Eine einfache Möglichkeit besteht darin, subplotmit denselben Argumenten erneut aufzurufen. Das wird aber schnell unelegant. Sie können auch das Figure-Objekt untersuchen und seine Liste der Axes-Objekte abrufen, was jedoch irreführend sein kann (Farbbalken sind auch Axes!). Die beste Lösung ist wahrscheinlich, ein Handle für jede von Ihnen erstellte Achse zu speichern, aber wenn Sie das tun, warum erstellen Sie dann nicht einfach alle Axes-Objekte am Anfang?

Der erste Ansatz besteht darin, erneut anzurufen plt.subplot:

import matplotlib.pyplot as plt

plt.subplot(1, 2, 1)
plt.plot([1, 2, 3], [0, 0.5, 0.2])

plt.subplot(1, 2, 2)
plt.plot([3, 2, 1], [0, 0.5, 0.2])

plt.suptitle('Implicit Interface: re-call subplot')

for i in range(1, 3):
    plt.subplot(1, 2, i)
    plt.xlabel('Boo')

( Quellcode , png )

../../_images/api_interfaces-6.png

Die zweite besteht darin, ein Handle zu speichern:

import matplotlib.pyplot as plt

axs = []
ax = plt.subplot(1, 2, 1)
axs += [ax]
plt.plot([1, 2, 3], [0, 0.5, 0.2])

ax = plt.subplot(1, 2, 2)
axs += [ax]
plt.plot([3, 2, 1], [0, 0.5, 0.2])

plt.suptitle('Implicit Interface: save handles')

for i in range(2):
    plt.sca(axs[i])
    plt.xlabel('Boo')

( Quellcode , png )

../../_images/api_interfaces-7.png

Der empfohlene Weg wäre jedoch, von Anfang an explizit zu sein:

import matplotlib.pyplot as plt

fig, axs = plt.subplots(1, 2)
axs[0].plot([1, 2, 3], [0, 0.5, 0.2])
axs[1].plot([3, 2, 1], [0, 0.5, 0.2])
fig.suptitle('Explicit Interface')
for i in range(2):
    axs[i].set_xlabel('Boo')

( Quellcode , png )

../../_images/api_interfaces-8.png

"Datenobjekt"-Schnittstellen von Drittanbieter-Bibliotheken #

Einige Bibliotheken von Drittanbietern haben sich entschieden, das Plotten für ihre Datenobjekte zu implementieren, z. B. data.plot()wird in pandas, xarray und anderen Bibliotheken von Drittanbietern angezeigt. Zur Veranschaulichung kann eine Downstream-Bibliothek einen einfachen Datencontainer implementieren, in dem Daten xund yDaten zusammen gespeichert sind, und dann eine plotMethode implementieren:

import matplotlib.pyplot as plt

# supplied by downstream library:
class DataContainer:

    def __init__(self, x, y):
        """
        Proper docstring here!
        """
        self._x = x
        self._y = y

    def plot(self, ax=None, **kwargs):
        if ax is None:
            ax = plt.gca()
        ax.plot(self._x, self._y, **kwargs)
        ax.set_title('Plotted from DataClass!')
        return ax


# what the user usually calls:
data = DataContainer([0, 1, 2, 3], [0, 0.2, 0.5, 0.3])
data.plot()

( Quellcode , png )

../../_images/api_interfaces-9.png

So kann die Bibliothek alle Einzelheiten vor dem Benutzer verbergen und eine dem Datentyp angemessene Visualisierung erstellen, oft mit guten Beschriftungen, einer Auswahl an Farbkarten und anderen praktischen Funktionen.

Oben hat uns jedoch möglicherweise der von der Bibliothek bereitgestellte Titel nicht gefallen. Glücklicherweise geben sie uns die Axes aus der plot()Methode zurück, und wenn wir die explizite Axes-Schnittstelle verstehen, könnten wir aufrufen: um den Titel anzupassen.ax.set_title('My preferred title')

Viele Bibliotheken erlauben ihren plotMethoden auch, ein optionales ax - Argument zu akzeptieren. Auf diese Weise können wir die Visualisierung in einer von uns platzierten und möglicherweise angepassten Achse platzieren.

Zusammenfassung #

Insgesamt ist es hilfreich, die explizite „Axes“-Schnittstelle zu verstehen, da sie die flexibelste ist und den anderen Schnittstellen zugrunde liegt. Ein Benutzer kann normalerweise herausfinden, wie er zur expliziten Schnittstelle herunterfällt und die zugrunde liegenden Objekte bearbeitet. Während die Einrichtung der expliziten Schnittstelle etwas ausführlicher sein kann, sind komplizierte Plots oft einfacher als der Versuch, die implizite "Pyplot" -Schnittstelle zu verwenden.

Notiz

Es ist manchmal verwirrend, dass wir pyplotfür beide Schnittstellen importieren. Derzeit pyplotimplementiert das Modul die "pyplot"-Schnittstelle, bietet aber auch Top-Level-Erstellungsmethoden für Figuren und Achsen und dreht schließlich die grafische Benutzeroberfläche hoch, falls eine verwendet wird. Wird also pyplotimmer noch benötigt, unabhängig von der gewählten Schnittstelle.

In ähnlicher Weise verwenden die von Partnerbibliotheken bereitgestellten deklarativen Schnittstellen die Objekte, auf die über die Schnittstelle „Axes“ zugegriffen werden kann, und akzeptieren diese häufig als Argumente oder geben sie von Methoden zurück. Normalerweise ist es wichtig, die explizite „Axes“-Schnittstelle zu verwenden, um Anpassungen an der Standardvisualisierung vorzunehmen oder die Daten in NumPy-Arrays zu entpacken und direkt an Matplotlib zu übergeben.

Anhang: Schnittstelle "Achsen" mit Datenstrukturen #

Die meisten AxesMethoden erlauben noch eine weitere API-Adressierung, indem sie ein Datenobjekt an die Methode übergeben und die Argumente als Strings angeben:

import matplotlib.pyplot as plt

data = {'xdat': [0, 1, 2, 3], 'ydat': [0, 0.2, 0.4, 0.1]}
fig, ax = plt.subplots(figsize=(2, 2))
ax.plot('xdat', 'ydat', data=data)

( Quellcode , png )

../../_images/api_interfaces-10.png

Anhang: "pylab"-Schnittstelle #

Es gibt eine weitere Schnittstelle, von der dringend abgeraten wird, und das ist im Grunde genommen . Dadurch können Benutzer einfach anrufen . Dies ist zwar praktisch, kann aber zu offensichtlichen Problemen führen, wenn der Benutzer einer Variablen unwissentlich denselben Namen wie einer Pyplot-Methode gibt.from matplotlib.pyplot import *plot(x, y)