HOWTO · Matplotlib
Wie erstellt man einen Oberflächenplot in Matplotlib
Wir können einen Oberflächenplot in Matplotlib mit der Methode plot_surface() erstellen.
Auf dieser Seite
Für einen 3D-Oberflächenplot in Matplotlib benötigen Sie zueinander passende zweidimensionale Arrays X, Y und Z. Erstellen Sie eine Achse mit projection="3d" und übergeben Sie die Arrays an Axes3D.plot_surface. Das Beispiel erstellt aus einer mathematischen Funktion ein Koordinatengitter, beschriftet die Achsen, fügt eine Farbskala hinzu und speichert die Abbildung. Derselbe Ablauf eignet sich für Messwerte, sofern sich Koordinaten und Höhen auf einem rechteckigen Gitter darstellen lassen.
Die Umgebung einrichten
Installieren Sie NumPy für Array- und Gitteroperationen und Matplotlib zum Erstellen von Diagrammen. Führen Sie im Terminal python -m pip install numpy matplotlib in der Python-Umgebung aus, die Sie verwenden möchten. Wenn Sie Pakete bereits über eine Umgebung oder ein Notebook verwalten, installieren Sie beide Pakete dort, damit sie dem Interpreter zur Verfügung stehen, der Ihr Skript ausführt.
Das Beispiel importiert NumPy und matplotlib.pyplot. Die 3D-Diagrammfunktionen sind in Matplotlib enthalten. Mit projection="3d" erstellen Sie eine 3D-Achse; ein separater Import von Axes3D ist daher nicht erforderlich. Die verwendete Methode dieser Achse ist Axes3D.plot_surface.
Die Daten vorbereiten
Ein Oberflächenplot ordnet jedem Punkt einer Ebene mit zwei Koordinaten eine Höhe zu. Bei gleichmäßig verteilten Koordinaten erzeugt np.linspace() eindimensionale Koordinatenwerte, und np.meshgrid() erweitert sie zu zweidimensionalen Gittern X und Y. Berechnen Sie Z anhand dieser Gitter oder geben Sie Messwerte an, die denselben Gitterpunkten zugeordnet sind.
Die drei Arrays müssen zueinander passende Formen haben: Jeder Wert Z[i, j] ist die Höhe am Koordinatenpaar X[i, j], Y[i, j]. Aktuelle Matplotlib-Versionen akzeptieren auch eindimensionale x- und y-Koordinatenvektoren und erweitern sie passend zu einem zweidimensionalen Z; das Höhenarray selbst muss jedoch weiterhin zu den Gitterdimensionen passen: Ein Z, das auf einem anderen Gitter als X und Y berechnet wurde, löst einen ValueError aus, wie der Abschnitt zur Fehlerbehebung unten an einem echten Lauf zeigt. Erstellen Sie zuerst die Koordinatengitter und berechnen oder formen Sie anschließend die Höhenwerte auf denselben Gittern um. Bilden Messwerte kein rechteckiges Gitter, bereiten Sie passende Gitterdaten vor oder interpolieren Sie diese, bevor Sie plot_surface verwenden.
Den Oberflächenplot erstellen
Dieses vollständige Beispiel verwendet die glatte radiale Funktion sin(sqrt(x² + y²)). Es erstellt die Gitter, zeichnet die Oberfläche, beschriftet alle drei Dimensionen, fügt eine Farbskala hinzu und speichert das Ergebnis im aktuellen Verzeichnis unter surface-plot.png. Führen Sie es in einer Umgebung aus, in der NumPy und Matplotlib installiert sind. Das Beispiel gibt nichts in der Konsole aus. Das Ergebnis ist eine gespeicherte Bilddatei sowie ein Matplotlib-Fenster, sofern das aktive Backend die Anzeige unterstützt. Die sichtbaren Achsen-, Titel- und Farbskalenbeschriftungen des unveränderten Beispiels bleiben auf Englisch.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
surface = ax.plot_surface(X, Y, Z, cmap="viridis")
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_title("Surface Plot")
fig.colorbar(surface, ax=ax, label="Z value")
fig.savefig("surface-plot.png", dpi=150, bbox_inches="tight")
plt.show()
Da dieses Skript keinen Text ausgibt, gibt es keinen Konsolenausgabeblock. Die Farbskala ordnet den Oberflächenfarben ihre Werte zu: Das Gitter bestimmt die Geometrie, während die Farbpalette die Darstellung steuert. In einem Notebook wird die Abbildung normalerweise von der Plot-Umgebung angezeigt. In einem Skript fordert plt.show() das konfigurierte Matplotlib-Backend zur Anzeige auf.
Den Oberflächenplot anpassen
Das folgende Beispiel wendet die häufigsten Anpassungen auf dieselbe Oberfläche an. Es wechselt die Farbpalette zu plasma, entfernt die Gitterlinien und dreht die Kamera auf eine feste Elevation und einen festen Azimut, bevor es die Farbskala hinzufügt und die Abbildung als customized-surface-plot.png speichert.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
surface = ax.plot_surface(X, Y, Z, cmap="plasma", edgecolor="none")
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_title("Customized Surface Plot")
ax.view_init(elev=30, azim=45)
fig.colorbar(surface, ax=ax, label="Z value")
fig.savefig("customized-surface-plot.png", dpi=150, bbox_inches="tight")
plt.show()
Wählen Sie eine Farbpalette, mit der sich die Änderungen in Z gut erkennen lassen. In diesem Beispiel ersetzt cmap="plasma" den Farbverlauf viridis des ersten Beispiels, und die Farbskala hilft dabei, diese Zuordnung zu verstehen. Die Option edgecolor="none" entfernt die gezeichneten Gitterlinien, die bei einem dichten Gitter von einer zusammenhängenden Oberfläche ablenken können; behalten Sie die Standardlinien bei, wenn das Abtastgitter selbst sichtbar bleiben soll.
Um die Kamera zu ändern, rufen Sie ax.view_init(elev=30, azim=45) auf, bevor Sie die Abbildung speichern oder anzeigen. elev ändert die Betrachtungshöhe und azim dreht die Ansicht um die vertikale Achse. Passen Sie diese Werte an, bis Form und Achsen gut zu erkennen sind; welcher Winkel am besten geeignet ist, hängt von den Daten und der gewünschten Darstellung ab. Im Vergleich zur ersten Abbildung zeigt die gedrehte Kamera in der zweiten Abbildung mehr von der rückwärtigen Flanke des zentralen Gipfels.
Bei einem dichten Gitter kann plot_surface die Anzahl der abgetasteten Zeilen und Spalten über Optionen wie rcount und ccount steuern. Niedrigere Werte zeichnen weniger Zeilen und Spalten ab und können eine große Oberfläche schneller rendern, verringern dabei aber den sichtbaren Detailgrad. Verwenden Sie genügend Abtastpunkte, um wichtige Änderungen in den Daten zu erhalten. Speichern Sie ein Bild zum Teilen mit fig.savefig("surface-plot.png", dpi=150, bbox_inches="tight"). Rufen Sie diese Methode vor plt.show() auf, damit sie auch mit Anzeige-Backends funktioniert, die die Abbildung nach dem Anzeigen schließen. Verwenden Sie einen anderen Dateinamen oder ein anderes Verzeichnis, wenn Sie mehrere Versionen behalten möchten.
Mit einem Drahtgitterplot vergleichen
Ein Drahtgitterplot zeichnet nur die Gitterlinien derselben Oberfläche, ohne gefüllte Flächen und ohne Farbpalette. Axes3D.plot_wireframe akzeptiert dieselben Gitter X, Y und Z, sodass Sie zwischen beiden Ansichten wechseln können, ohne neue Daten vorzubereiten. Ein Drahtgitter hilft, wenn die Gitterstruktur selbst wichtig ist, wenn eine gefüllte Oberfläche die Rückseite der Form verdecken würde, oder als schneller Strukturcheck unbekannter Daten, bevor Sie eine vollständige Oberfläche rendern.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2, color="tab:blue")
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_title("Wireframe Plot")
fig.savefig("wireframe-plot.png", dpi=150, bbox_inches="tight")
plt.show()
Die Argumente rstride und cstride überspringen Zeilen und Spalten, damit die Linien lesbar bleiben; das Beispiel zeichnet jede zweite Zeile und Spalte eines 50×50-Gitters. Anders als plot_surface hat ein Drahtgitter keine Flächenfarben, sodass eine Farbskala nichts erklären könnte. Für eine endgültige Präsentation vermittelt die gefüllte Oberfläche Höhenunterschiede meist besser, während das Drahtgitter deutlicher zeigt, wie das Gitter selbst abgetastet ist.
Fehler durch nicht passende Formen beheben
Der häufigste Fehler bei plot_surface ist ein Z-Array, dessen Form nicht zu den Koordinatengittern passt. Das folgende Skript berechnet Z auf einem 50×50-Gitter, übergibt es aber zusammen mit den 100×100-Gittern X und Y:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
x_small = np.linspace(-5, 5, 50)
y_small = np.linspace(-5, 5, 50)
X_small, Y_small = np.meshgrid(x_small, y_small)
Z = np.sin(np.sqrt(X_small**2 + Y_small**2))
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.plot_surface(X, Y, Z, cmap="viridis")
plt.show()
Beim Ausführen stoppt das Skript am Aufruf von plot_surface mit diesem Fehler:
ValueError: shape mismatch: objects cannot be broadcast to a single shape. Mismatch is between arg 0 with shape (100, 100) and arg 2 with shape (50, 50).
Um den Fehler zu beheben, berechnen Sie Z aus denselben Gittern, die Sie an plot_surface übergeben, wie im ersten Beispiel, sodass Z.shape mit X.shape und Y.shape übereinstimmt. Wenn Sie unsicher sind, geben Sie die drei Formen vor dem Plotten aus und vergleichen Sie sie: Jeder Eintrag von Z braucht genau ein Koordinatenpaar, nicht mehr und nicht weniger.
Fazit
Die wichtigsten Schritte sind: Koordinatengitter erstellen, Z an diese Gitter anpassen, eine 3D-Achse hinzufügen und Axes3D.plot_surface aufrufen. Eine Farbpalette und eine Farbskala erklären die Höhenwerte, während Ansichts- und Abtastoptionen helfen, die Form klar darzustellen. Wenn Sie das Gitter selbst untersuchen müssen, stellt plot_wireframe dieselben Daten als Linien dar. Speichern Sie die Abbildung, wenn Sie eine Bilddatei benötigen, und passen Sie die Gitterauflösung oder die Kamera an die Daten an, die Sie plotten.
Häufig gestellte Fragen
-
Welche Daten eignen sich für einen Oberflächenplot?
Verwenden Sie Werte, die über zwei Koordinaten definiert sind, wobei jede Höhe einem Punkt auf einem rechteckigen Gitter entspricht. Für ein Beispiel eignet sich eine Funktion; Messwerte sind ebenfalls verwendbar, wenn sie auf zueinander passenden Koordinatengittern angeordnet sind. Verstreute Punkte müssen zuerst in ein Gitter überführt werden. -
Wie installiere ich die benötigten Bibliotheken?
Installieren Sie NumPy und Matplotlib in der Umgebung, in der Ihr Skript ausgeführt wird, mitpython -m pip install numpy matplotlib. -
Kann ich die Farben der Oberfläche ändern?
Ja. Setzen Sie das Argumentcmapvonplot_surfaceund fügen Sie anschließend mitfig.colorbar(surface, ax=ax)eine Farbskala hinzu. Sie zeigt, welche Werte den Farben entsprechen. -
Wie ändere ich den Blickwinkel?
Verwenden Sieax.view_init(elev=..., azim=...). Die Elevation ändert die Höhe der Kamera, der Azimut dreht ihre Position um den Plot. -
Warum müssen
X,YundZzueinander passende Formen haben?
Matplotlib benötigt für jeden Gitterpunkt ein Koordinatenpaar und eine zugehörige Höhe. WurdeZauf einem anderen Gitter berechnet, löstplot_surfaceeinenValueErrorzu Formen aus, die nicht gemeinsam broadcastet werden können. Erstellen Sie die Koordinatengitter mitnp.meshgrid()und berechnen SieZaus denselben Gittern, damit die entsprechenden Einträge zusammenpassen.