Matplotlib Tutorial: Spines und Ticks


Verschieben der Grenzlinien und Polierung der Achsenbezeichnungen

spines

Der Begriff "spine" wohl meistens bekannt in Bezug auf das Rückgrat oder die Wirbelsäule des menschlichen Skeletts. Eine weitere Bedeutung steht für eine "Buch-Hülle". Unser Bild auf der rechten Seite zeigt die Stacheln eines Kaktus, künstlerisch verändert, damit es aussieht wie ein Brustkorb. Sie werden in einer Bibliothek kaum etwas finden zur Anwendung von Matplotlib. Stacheln in Matplotlib bezeichnen die Linien, welche die Achsen-Markierungen verbinden unter Berücksichtigung des Datenbereichs.

Wir demonstrieren im Folgenden, dass die Stacheln (spines) an beliebigen Stellen gesetzt werden können.

Bevor wir damit beginnen können, führen wir die gca-Funktion ein. Diese liefert zu aktuellen Instanzen der Achsen der aktuellen Figur zurück.

Wir können zum Beispiel plt.gca(projection='polar') aufrufen um die aktuellen Polar-Achsen zu erhalten.

# the next "inline" statement is only needed,
# if you are working with "ipython notebook"
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
X  = np.linspace(-2 * np.pi, 2 * np.pi, 70, endpoint=True)
F1 = np.sin(2* X)
F2 = (2*X**5 + 4*X**4 - 4.8*X**3 + 1.2*X**2 + X + 1)*np.exp(-X**2)
# get the current axes, creating them if necessary:
ax = plt.gca()
# making the top and right spine invisible:
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
# moving bottom spine up to y=0 position:
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
# moving left spine to the right to position x == 0:
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
plt.plot(X, F1)
plt.plot(X, F2)
plt.show()


Ticks anpassen

Matplotlib hat bis jetzt - in allen vorangegangenen Beispielen - automatisch den Abstand der Punkte auf der Achse ermittelt. In unserem vorigen Beispiel haben wir gesehen dass die X-Achse mit -8, -6. -4, -2, 0, 2, 4, 6, 8 nummeriert war, während die Y-Achse mit -2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0 beschriftet ist.

xticks ist eine Methode, die für das Abfragen und Verändern von Tick-Positionen und Beschriftungen benutzt werden kann. Das gleiche gilt für die Methode yticks.

# get the current axes, creating them if necessary:
ax = plt.gca()
locs, labels = plt.xticks()
print(locs, labels)
locs, labels = plt.yticks()
print(locs, labels)
[ 0.   0.2  0.4  0.6  0.8  1. ] <a list of 6 Text xticklabel objects>
[ 0.   0.2  0.4  0.6  0.8  1. ] <a list of 6 Text yticklabel objects>

Wie bereits erwähnt, kann xticks ebenso dazu verwendet werden, um die Position der Ticks auf der X-Achse zu verändern:

plt.xticks( np.arange(10) )
locs, labels = plt.xticks()
print(locs, labels)
[0 1 2 3 4 5 6 7 8 9] <a list of 10 Text xticklabel objects>

Jetzt verändern wir sowohl die Position als auch die Beschriftung der Ticks auf der X-Achse:

# set the locations and labels of the xticks
plt.xticks( np.arange(4), 
           ('Berlin', 'London', 'Hamburg', 'Toronto') )
Der obige Code liefert folgendes Ergebnis:
([<matplotlib.axis.XTick at 0x10ccbfef0>,
  <matplotlib.axis.XTick at 0x10ca7e320>,
  <matplotlib.axis.XTick at 0x10bead588>,
  <matplotlib.axis.XTick at 0x10cedff98>],
 <a list of 4 Text xticklabel objects>)

Gehen wir nochmal zurück zum vorigen Beispiel der Trigonometrischen Funktionen. Die meisten werden Faktoren von Pi für die X-Achse für geeigneter halten als die einfachen Integer-Werte:

import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-2 * np.pi, 2 * np.pi, 70, endpoint=True)
X = np.linspace(-2 * np.pi, 2 * np.pi, 70, endpoint=True)
F1 = np.sin(X**2)
F2 = X * np.sin(X)
# get the current axes, creating them if necessary:
ax = plt.gca()
# making the top and right spine invisible:
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
# moving bottom spine up to y=0 position:
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
# moving left spine to the right to position x == 0:
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
plt.xticks( [-6.28, -3.14, 3.14, 6.28])
plt.yticks([-3, -1, 0, +1, 3])
plt.plot(X, F1)
plt.plot(X, F2)
plt.show()


Verändern der Tick-Beschriftungen

Wir möchten nun die Beschriftungen der Ticks auf der X-Achse umbenennen und durch eigene Markierungen ersetzen. Wir benutzen dafür ebenfalls die Methode xticks wie auch schon im vorigen Beispiel. Diesesmal jedoch, rufen wir xticks mit zwei Parametern auf: Der erste ist die gleiche Liste die wir auch schon vorher benutzt haben, d.h. Positionen auf der X-Achse, an denen die Ticks gesetzt werden sollen. Der zweite Parameter ist eine Liste der gleichen Größe mit den entsprechenden LaTeX Tick-Markierungen, d.h. der Text der anstelle der Werte sehen möchten. Die LaTeX-Schreibweise muss ein raw-String sein um den Escape-Mechanismus von Python abzustellen, da in LaTeX das Backslash sehr stark genutzt wird.

import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-2 * np.pi, 2 * np.pi, 70, endpoint=True)
F1 = X * np.sin(X)
ax = plt.gca()
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
# labelling the X ticks:
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)
plt.show()


Justierung der Tick-Beschriftungen

Wir wollen die Lesbarkeit der Tick-Beschriftungen erhöhen. Dazu vergrößern wir die Schrift und zeichnen dies auf einen halbtransparenten Hintergrund.

print(ax.get_xticklabels())
<a list of 4 Text xticklabel objects>
for xtick in ax.get_xticklabels():
    print(xtick)
Text(-6.28,0,'$-2\\pi$')
Text(-3.14,0,'$-\\pi$')
Text(3.14,0,'$+\\pi$')
Text(6.28,0,'$+2\\pi$')
labels = [xtick.get_text() for xtick in ax.get_xticklabels()]
print(labels)
['$-2\\pi$', '$-\\pi$', '$+\\pi$', '$+2\\pi$']

Jetzt vergrößern wir die Schrift und stellen die Transparenz ein:

import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-2 * np.pi, 2 * np.pi, 170, endpoint=True)
F1 = np.sin(X**3 / 2)
ax = plt.gca()
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
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])
for xtick in ax.get_xticklabels():
    xtick.set_fontsize(18)
    xtick.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.7 ))
for ytick in ax.get_yticklabels():
    ytick.set_fontsize(14)
    ytick.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.7 ))
    
plt.plot(X, F1, label="$sin(x)$")
plt.legend(loc='lower left')
plt.show()