Text in Matplotlib#

Matplotlib bietet umfangreiche Textunterstützung, einschließlich Unterstützung für mathematische Ausdrücke, TrueType-Unterstützung für Raster- und Vektorausgaben, zeilenumbruchgetrennten Text mit beliebiger Rotation und Unicode-Unterstützung.

Da Schriften direkt in Ausgabedokumente, z. B. für PostScript oder PDF, eingebettet werden, sehen Sie auf dem Bildschirm das Gleiche wie auf dem Ausdruck. Die FreeType-Unterstützung erzeugt sehr schöne, geglättete Schriften, die auch bei kleinen Rastergrößen gut aussehen. Matplotlib enthält seinen eigenen matplotlib.font_manager (dank Paul Barrett), der einen plattformübergreifenden, W3C-konformen Algorithmus zur Schriftfinderung implementiert.

Der Benutzer hat mit sinnvollen Standardeinstellungen in der rc-Datei viel Kontrolle über Texteigenschaften (Schriftgröße, Schriftgewicht, Textposition und -farbe usw.). Und wichtig für alle, die sich für mathematische oder wissenschaftliche Grafiken interessieren: Matplotlib implementiert eine große Anzahl von TeX-Math-Symbolen und -Befehlen und unterstützt mathematische Ausdrücke überall in Ihrer Grafik.

Grundlegende Textbefehle#

Die folgenden Befehle werden zum Erstellen von Text in der impliziten und expliziten Schnittstelle verwendet (siehe Matplotlib Application Interfaces (APIs) für eine Erklärung der Kompromisse)

implizite API

explizite API

Beschreibung

text

text

Fügt Text an einer beliebigen Stelle der Axes hinzu.

annotate

annotate

Fügt eine Anmerkung mit einem optionalen Pfeil an einer beliebigen Stelle der Axes hinzu.

xlabel

set_xlabel

Fügt eine Beschriftung zur x-Achse der Axes hinzu.

ylabel

set_ylabel

Fügt eine Beschriftung zur y-Achse der Axes hinzu.

title

set_title

Fügt einen Titel zu den Axes hinzu.

figtext

text

Fügt Text an einer beliebigen Stelle der Figure hinzu.

suptitle

suptitle

Fügt einen Titel zur Figure hinzu.

Alle diese Funktionen erstellen und geben eine Text-Instanz zurück, die mit einer Vielzahl von Schrift- und anderen Eigenschaften konfiguriert werden kann. Das folgende Beispiel zeigt all diese Befehle in Aktion, und weitere Details finden Sie in den folgenden Abschnitten.

import matplotlib.pyplot as plt

import matplotlib

fig = plt.figure()
ax = fig.add_subplot()
fig.subplots_adjust(top=0.85)

# Set titles for the figure and the subplot respectively
fig.suptitle('bold figure suptitle', fontsize=14, fontweight='bold')
ax.set_title('axes title')

ax.set_xlabel('xlabel')
ax.set_ylabel('ylabel')

# Set both x- and y-axis limits to [0, 10] instead of default [0, 1]
ax.axis([0, 10, 0, 10])

ax.text(3, 8, 'boxed italics text in data coords', style='italic',
        bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})

ax.text(2, 6, r'an equation: $E=mc^2$', fontsize=15)

ax.text(3, 2, 'Unicode: Institut für Festkörperphysik')

ax.text(0.95, 0.01, 'colored text in axes coords',
        verticalalignment='bottom', horizontalalignment='right',
        transform=ax.transAxes,
        color='green', fontsize=15)

ax.plot([2], [1], 'o')
ax.annotate('annotate', xy=(2, 1), xytext=(3, 4),
            arrowprops=dict(facecolor='black', shrink=0.05))

plt.show()
bold figure suptitle, axes title

Beschriftungen für x- und y-Achse#

Das Festlegen der Beschriftungen für die x- und y-Achse ist einfach über die Methoden set_xlabel und set_ylabel möglich.

import matplotlib.pyplot as plt
import numpy as np

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('Time (s)')
ax.set_ylabel('Damped oscillation (V)')

plt.show()
text intro

Die x- und y-Beschriftungen werden automatisch so platziert, dass sie die x- und y-Tickbeschriftungen nicht verdecken. Vergleichen Sie die folgende Grafik mit der darüber und beachten Sie, dass sich die y-Beschriftung links von der oberen befindet.

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1*10000)
ax.set_xlabel('Time (s)')
ax.set_ylabel('Damped oscillation (V)')

plt.show()
text intro

Wenn Sie die Beschriftungen verschieben möchten, können Sie das Schlüsselwortargument *labelpad* angeben, wobei der Wert in Punkten angegeben wird (1/72 Zoll, die gleiche Einheit wie bei der Angabe von Schriftgrößen).

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1*10000)
ax.set_xlabel('Time (s)')
ax.set_ylabel('Damped oscillation (V)', labelpad=18)

plt.show()
text intro

Alternativ akzeptieren die Beschriftungen alle Text-Schlüsselwortargumente, einschließlich *position*, über das wir die Position der Beschriftungen manuell festlegen können. Hier platzieren wir die x-Beschriftung ganz links von der Achse. Beachten Sie, dass die y-Koordinate dieser Position keine Auswirkung hat – um die y-Position anzupassen, müssen wir das Schlüsselwortargument *labelpad* verwenden.

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('Time (s)', position=(0., 1e6), horizontalalignment='left')
ax.set_ylabel('Damped oscillation (V)')

plt.show()
text intro

Alle Beschriftungen in diesem Tutorial können durch Manipulation der Methode matplotlib.font_manager.FontProperties oder durch benannte Schlüsselwortargumente an set_xlabel geändert werden.

from matplotlib.font_manager import FontProperties

font = FontProperties(family='Times New Roman', style='italic')

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('Time (s)', fontsize='large', fontweight='bold')
ax.set_ylabel('Damped oscillation (V)', fontproperties=font)

plt.show()
text intro

Schließlich können wir native TeX-Renderings in allen Textobjekten verwenden und mehrzeilige Texte erstellen

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.2, left=0.2)
ax.plot(x1, np.cumsum(y1**2))
ax.set_xlabel('Time (s) \n This was a long experiment')
ax.set_ylabel(r'$\int\ Y^2\ dt\ \ (V^2 s)$')
plt.show()
text intro

Titel#

Unterplottitel werden ähnlich wie Beschriftungen gesetzt, aber es gibt das Schlüsselwortargument *loc*, das die Position und Ausrichtung ändern kann (der Standardwert ist "center").

fig, axs = plt.subplots(3, 1, figsize=(5, 6), tight_layout=True)
locs = ['center', 'left', 'right']
for ax, loc in zip(axs, locs):
    ax.plot(x1, y1)
    ax.set_title('Title with loc at ' + loc, loc=loc)
plt.show()
Title with loc at center, Title with loc at left, Title with loc at right

Der vertikale Abstand für Titel wird über rcParams["axes.titlepad"] (Standard: 6.0) gesteuert. Das Einstellen auf einen anderen Wert verschiebt den Titel.

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(top=0.8)
ax.plot(x1, y1)
ax.set_title('Vertically offset title', pad=30)
plt.show()
Vertically offset title

Ticks und Tickbeschriftungen#

Das Platzieren von Ticks und Tickbeschriftungen ist ein sehr kniffliger Aspekt bei der Erstellung einer Grafik. Matplotlib tut sein Bestes, um die Aufgabe automatisch zu erledigen, bietet aber auch ein sehr flexibles Framework zur Bestimmung der Tickpositionen und deren Beschriftung.

Terminologie#

Achsen haben ein matplotlib.axis.Axis-Objekt für die ax.xaxis und ax.yaxis, die die Informationen über die Anordnung der Beschriftungen in der Achse enthalten.

Die Achsen-API wird im Detail in der Dokumentation zu axis erläutert.

Ein Achsenobjekt hat Haupt- und Neben-Ticks. Die Achse verfügt über die Methoden Axis.set_major_locator und Axis.set_minor_locator, die die zu plottenden Daten verwenden, um die Position von Haupt- und Neben-Ticks zu bestimmen. Es gibt auch die Methoden Axis.set_major_formatter und Axis.set_minor_formatter, die die Tickbeschriftungen formatieren.

Einfache Ticks#

Es ist oft praktisch, einfach die Tickwerte und manchmal die Tickbeschriftungen zu definieren und damit die Standard-Locator und -Formatter zu überschreiben. Dies wird jedoch nicht empfohlen, da es die interaktive Navigation des Plots unterbricht. Außerdem kann es die Achsenlimits zurücksetzen: Beachten Sie, dass die zweite Grafik die gewünschten Ticks enthält, einschließlich solcher, die weit außerhalb der automatischen Ansichtsgrenzen liegen.

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
axs[1].xaxis.set_ticks(np.arange(0., 8.1, 2.))
plt.show()
text intro

Wir können dies natürlich nachträglich korrigieren, aber es unterstreicht eine Schwäche des Hardcodierens von Ticks. Dieses Beispiel ändert auch das Format der Ticks

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
ticks = np.arange(0., 8.1, 2.)
# list comprehension to get all tick labels...
tickla = [f'{tick:1.2f}' for tick in ticks]
axs[1].xaxis.set_ticks(ticks)
axs[1].xaxis.set_ticklabels(tickla)
axs[1].set_xlim(axs[0].get_xlim())
plt.show()
text intro

Tick-Locator und -Formatter#

Anstatt eine Liste aller Tickbeschriftungen zu erstellen, hätten wir matplotlib.ticker.StrMethodFormatter (neuer Stil str.format() Format-String) oder matplotlib.ticker.FormatStrFormatter (alter Stil '%' Format-String) verwenden und an ax.xaxis übergeben können. Ein matplotlib.ticker.StrMethodFormatter kann auch durch Übergabe eines str erstellt werden, ohne den Formatter explizit erstellen zu müssen.

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
ticks = np.arange(0., 8.1, 2.)
axs[1].xaxis.set_ticks(ticks)
axs[1].xaxis.set_major_formatter('{x:1.1f}')
axs[1].set_xlim(axs[0].get_xlim())
plt.show()
text intro

Und natürlich hätten wir einen nicht standardmäßigen Locator verwenden können, um die Tickpositionen festzulegen. Beachten Sie, dass wir immer noch die Tickwerte übergeben, aber die oben verwendete x-Limit-Korrektur ist *nicht* erforderlich.

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
locator = matplotlib.ticker.FixedLocator(ticks)
axs[1].xaxis.set_major_locator(locator)
axs[1].xaxis.set_major_formatter({x}°')
plt.show()
text intro

Der Standard-Formatter ist der matplotlib.ticker.MaxNLocator, aufgerufen als ticker.MaxNLocator(self, nbins='auto', steps=[1, 2, 2.5, 5, 10]). Das Argument steps enthält eine Liste von Vielfachen, die für Tickwerte verwendet werden können. In diesem Fall wären 2, 4, 6 akzeptable Ticks, ebenso wie 20, 40, 60 oder 0,2, 0,4, 0,6. 3, 6, 9 wären jedoch nicht akzeptabel, da 3 nicht in der Liste der Schritte vorkommt.

Die Einstellung von nbins=auto verwendet einen Algorithmus, um zu bestimmen, wie viele Ticks für die Achsenlänge akzeptabel sind. Die Schriftgröße der Tickbeschriftung wird berücksichtigt, die Länge des Tick-Strings jedoch nicht (da sie noch nicht bekannt ist). In der unteren Reihe sind die Tickbeschriftungen ziemlich groß, daher setzen wir nbins=4, damit die Beschriftungen in der rechten Grafik Platz finden.

fig, axs = plt.subplots(2, 2, figsize=(8, 5), tight_layout=True)
for n, ax in enumerate(axs.flat):
    ax.plot(x1*10., y1)

formatter = matplotlib.ticker.FormatStrFormatter('%1.1f')
locator = matplotlib.ticker.MaxNLocator(nbins='auto', steps=[1, 4, 10])
axs[0, 1].xaxis.set_major_locator(locator)
axs[0, 1].xaxis.set_major_formatter(formatter)

formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
locator = matplotlib.ticker.AutoLocator()
axs[1, 0].xaxis.set_major_formatter(formatter)
axs[1, 0].xaxis.set_major_locator(locator)

formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
locator = matplotlib.ticker.MaxNLocator(nbins=4)
axs[1, 1].xaxis.set_major_formatter(formatter)
axs[1, 1].xaxis.set_major_locator(locator)

plt.show()
text intro

Schließlich können wir Funktionen für den Formatter mit matplotlib.ticker.FuncFormatter angeben. Darüber hinaus wird, wie bei matplotlib.ticker.StrMethodFormatter, durch Übergabe einer Funktion automatisch ein matplotlib.ticker.FuncFormatter erstellt.

def formatoddticks(x, pos):
    """Format odd tick positions."""
    if x % 2:
        return f'{x:1.2f}'
    else:
        return ''


fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.plot(x1, y1)
locator = matplotlib.ticker.MaxNLocator(nbins=6)
ax.xaxis.set_major_formatter(formatoddticks)
ax.xaxis.set_major_locator(locator)

plt.show()
text intro

Datums-Ticks#

Matplotlib kann datetime.datetime und numpy.datetime64-Objekte als Plot-Argumente akzeptieren. Daten und Zeiten erfordern eine spezielle Formatierung, die oft von manuellen Eingriffen profitieren kann. Um zu helfen, haben Daten spezielle Locator und Formatter, die im Modul matplotlib.dates definiert sind.

Das folgende einfache Beispiel veranschaulicht dieses Konzept. Beachten Sie, wie wir die Tickbeschriftungen drehen, damit sie sich nicht überlappen.

import datetime

fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
base = datetime.datetime(2017, 1, 1, 0, 0, 1)
time = [base + datetime.timedelta(days=x) for x in range(len(x1))]

ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()
text intro

Wir können ein Format an matplotlib.dates.DateFormatter übergeben. Wenn zwei Tickbeschriftungen sehr nah beieinander liegen, können wir die Klasse dates.DayLocator verwenden, mit der wir eine Liste von Tagen des Monats angeben können, die verwendet werden sollen. Ähnliche Formatter sind im Modul matplotlib.dates aufgeführt.

import matplotlib.dates as mdates

locator = mdates.DayLocator(bymonthday=[1, 15])
formatter = mdates.DateFormatter('%b %d')

fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()
text intro

Legenden und Anmerkungen#

Gesamtlaufzeit des Skripts: (0 Minuten 5,399 Sekunden)

Galerie generiert von Sphinx-Gallery