Datenvisualisierung mit

Matplotlib

Als erstes: IPython interaktiv machen:

In [1]:
%matplotlib inline
# bei euch: %matplotlib (nur in iPython)

Um mit Matplotlib arbeiten zu können, muss die Bibliothek erst einmal importiert werden. Damit wir nicht so viel tippen müssen geben wir ihr einen kürzeren Namen:

In [2]:
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (10, 8)
plt.rcParams['font.size'] = 16
plt.rcParams['lines.linewidth'] = 2

Außerdem brauchen wir ein paar Funktion aus numpy, die euch schon bekannt sind

In [3]:
import numpy as np

Ein einfaches Beispiel: $f(x)=x^2$

In [4]:
x = np.linspace(0, 1) # gibt 50 Zahlen in gleichmäßigem Abstand von 0–1
plt.plot(x, x**2)
# Falls nicht interaktiv: 
# plt.show()
Out[4]:
[<matplotlib.lines.Line2D at 0x7f6ab82d42b0>]

Anderes Beispiel: $\sin(t)$ mit verschiedenen Stilen. Vorsicht, die Funktionen und $\pi$ sind Bestandteil von numpy

In [5]:
t = np.linspace(0, 2 * np.pi)
plt.plot(t, np.sin(t))
Out[5]:
[<matplotlib.lines.Line2D at 0x7f6aab5aeeb0>]
In [6]:
plt.plot(t, np.sin(t), 'r--')
Out[6]:
[<matplotlib.lines.Line2D at 0x7f6aab521400>]
In [7]:
plt.plot(t, np.sin(t), 'go')
Out[7]:
[<matplotlib.lines.Line2D at 0x7f6aab505100>]

Tabelle mit allen Farben und Styles: matplotlib.axes.Axes.plot

Neue Grenzen mit xlim(a, b) und ylim(a, b)

In [8]:
plt.plot(t, np.sin(t))
plt.xlim(0, 2 * np.pi)
plt.ylim(-1.2, 1.2)
Out[8]:
(-1.2, 1.2)

Es fehlt noch etwas...

XKCD comic on why you should label your axes.

In [9]:
with plt.xkcd():
    plt.title('Axes with labels')
    plt.plot(t, np.sin(t))
    plt.xlabel('t / s')
    plt.ylabel('U / V')
    plt.ylim(-1.1, 1.1)
    plt.xlim(0, 2 * np.pi)
findfont: Font family ['xkcd', 'xkcd Script', 'Humor Sans', 'Comic Neue', 'Comic Sans MS'] not found. Falling back to DejaVu Sans.
findfont: Font family ['xkcd', 'xkcd Script', 'Humor Sans', 'Comic Neue', 'Comic Sans MS'] not found. Falling back to DejaVu Sans.

Achsen-Beschriftungen können mit LaTeX-Code erstellt werden → LaTeX-Kurs in der nächsten Woche.

In [10]:
plt.plot(t, np.sin(t))
plt.xlabel(r'$t / \mathrm{s}$')
plt.ylabel(r'$U / \mathrm{V}$')
Out[10]:
Text(0, 0.5, '$U / \\mathrm{V}$')

Einheiten in Achsenbeschriftungen werden wegdividiert:

In [11]:
plt.plot(t, np.sin(t))
plt.xlabel(r'$t / \mathrm{s}$')
plt.ylabel(r'$U \,/\, \mathrm{V}$')  # Spaces sind Geschmacksfrage……
Out[11]:
Text(0, 0.5, '$U \\,/\\, \\mathrm{V}$')

Mehr zu Einheiten gibt es im LaTeX-Kurs.

Legende

Legenden für Objekte die ein label tragen

In [12]:
plt.plot(t, np.sin(t), label=r'$\sin(t)$')
plt.legend()
#plt.legend(loc='lower left')
#plt.legend(loc='best')
Out[12]:
<matplotlib.legend.Legend at 0x7f6aab21e0d0>

Seit matplotlib 2.0.2 ist loc=best standardmäßig eingestellt.

Andere möglche Orte für die Legende findest du hier:

https://matplotlib.org/api/legend_api.html

Gitter

Mit grid() wird ein Gitter erstellt:

In [13]:
plt.plot(t, np.sin(t))
plt.grid()

Laden von Daten

In [14]:
x, y = np.genfromtxt('data/example_data_linear.txt', unpack=True)
plt.plot(x, y, 'k.')

t = np.linspace(0, 10)
plt.plot(t, 5 * t, 'r-')
Out[14]:
[<matplotlib.lines.Line2D at 0x7f6aab4d5850>]

Auslagern in ein Skript

Speichert den folgenden Code in eine Textdatei plot.py ab.

Öffnet ein Terminal und startet das Programm:

python plot.py
In [15]:
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 1)
plt.plot(x, x**2, 'b-')
plt.savefig('plot.pdf')

Mit savefig speichert man die Abbildung.

In diesem Fall sollte die Datei plot.pdf erstellt worden sein.

Es gibt viele Ausgabeformate: pdf, png, svg, LaTeX

Um mehrere Plots zu speichern kann man plt.clf() verwenden. Der Befehl leert die aktuelle figure und steht für clear figure.

In [16]:
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 1)

### Plot 1
plt.clf()


plt.plot(x, x**2, 'b-',label='Plot 1')
plt.legend()
plt.savefig('plot_1.pdf')

### Plot 2
plt.clf()

plt.plot(x, x**3, 'r-')
plt.savefig('plot_2.pdf')

Komplexere Abbildungen

Natürlich kann man mehrere Linien in einen Plot packen:

In [17]:
x = np.linspace(0, 1)

plt.plot(x, x**2, label=r'$x^2$')
plt.plot(x, x**4)
plt.plot(x, x**6, 'o', label=r'$x^6$')

plt.legend()
Out[17]:
<matplotlib.legend.Legend at 0x7f6aab10a4f0>

Es werden nur die Plots in der Legende angezeigt, die ein Label haben.

Man kann auch mehrere Plots in ein Bild packen:

In [18]:
x = np.linspace(0, 2 * np.pi)

# #rows, #columns, plot index = row * (#cols) + col
plt.subplot(2, 1, 1)
plt.plot(x, x**2)
plt.xlim(0, 2 * np.pi)

plt.subplot(2, 1, 2)
plt.plot(x, np.sin(x))
plt.xlim(0, 2 * np.pi)
Out[18]:
(0.0, 6.283185307179586)

Dies führt manchmal zu Spacing-Problemen und Teilen die sich überscheneiden, Lösung: plt.tight_layout()

In [19]:
x = np.linspace(0, 2 * np.pi)

# Anzahl Zeile, Anzahl Spalten, Nummer des Plots
plt.subplot(2, 1, 1)
plt.plot(x, x**2)
plt.xlim(0, 2 * np.pi)
plt.title(r"$f(x)=x^2$")

plt.subplot(2, 1, 2)
plt.plot(x, np.sin(x))
plt.xlim(0, 2 * np.pi)
plt.title(r"$f(x)=\sin(x)$")

plt.tight_layout()

Plot im Plot:

In [20]:
plt.plot(x, x**2)

# Koordinaten relativ zum Plot (0,0) links unten (1,1) rechts oben
plt.axes([0.2, 0.45, 0.3, 0.3]) 

# [x-location, y-location, x-length, y-length]

plt.plot(x, x**3)
Out[20]:
[<matplotlib.lines.Line2D at 0x7f6aaae96550>]

Plots mit Fehlerbalken

Sehr häufig werden im Praktikum Plots mit Fehlerbalken benötigt:

In [21]:
x = np.linspace(0, 2 * np.pi, 10)
errX = 0.4 * np.random.randn(10)
errY = 0.4 * np.random.randn(10)

plt.errorbar(x + errX, x + errY, xerr=0.4, yerr=errY, fmt='o')
Out[21]:
<ErrorbarContainer object of 3 artists>

Achsen-Skalierung

Logarithmische (oder auch andere) Skalierung der Achsen ist auch möglich:

In [22]:
x = np.linspace(0, 10)

plt.plot(x, np.exp(-x))
plt.yscale('log')
#plt.xscale('log')

Polar-Plot

Manchmal braucht man einen Polarplot:

In [23]:
#r = np.linspace(0, 10, 1000)
r = np.linspace(0, 10, 50)
theta = 2 * np.pi * r

plt.polar(theta, r)
Out[23]:
[<matplotlib.lines.Line2D at 0x7f6aab1635e0>]

Ticks

Man kann sehr viele Sachen mit Ticks machen…

In [24]:
x = np.linspace(0, 2 * np.pi)

plt.plot(x, np.sin(x))
plt.xlim(0, 2 * np.pi)
# erste Liste: Tick-Positionen, zweite Liste: Tick-Beschriftung
plt.xticks([0, np.pi / 2, np.pi, 3 * np.pi / 2, 2 * np.pi],
           [r"$0$", r"$\frac{1}{4}\tau$", r"$\frac{1}{2}\tau$", r"$\frac{3}{4}\tau$", r"$\tau$"])
plt.title(r"$\tau$ FTW!")
Out[24]:
Text(0.5, 1.0, '$\\tau$ FTW!')
In [25]:
months = ['January',
          'February',
          'March',
          'April',
          'May',
          'June',
          'July',
          'August',
          'September',
          'October',
          'November',
          'December']

plt.plot(np.arange(12), np.random.rand(12))
plt.xticks(np.arange(12), months, rotation=45, rotation_mode='anchor', ha='right', va='top')
plt.xlim(0, 11)
Out[25]:
(0.0, 11.0)

Histogramme

Sehr häufig braucht man Histogramme.

In [26]:
# Zufallsdaten generieren:
x = np.random.normal(0, 1, 1000)
plt.hist(x)
# try histtype='stepfilled'
Out[26]:
(array([  1.,  15.,  50., 165., 279., 249., 156.,  60.,  20.,   5.]),
 array([-3.41431674, -2.72906138, -2.04380602, -1.35855066, -0.6732953 ,
         0.01196006,  0.69721542,  1.38247078,  2.06772614,  2.7529815 ,
         3.43823686]),
 <BarContainer object of 10 artists>)

Objektorientiertes Plotten

Bis jetzt haben wir die schnelle Variante mit der pyplot-Syntax benutzt. Wenn man viele Plots anlegt, ist der objekt-orientierte Ansatz für matplotlib besser geeignet.

In [27]:
import matplotlib.pyplot as plt
import numpy as np

t = np.linspace(0, 2*np.pi, 1000)

fig, (ax1, ax2) = plt.subplots(2, 1)

ax1.plot(t, np.sin(t), 'r-')
ax1.set_title(r"$f(t)=\sin(t)$")
ax1.set_xlabel("$t$")
ax1.set_xlim(0, 2 * np.pi)
ax1.set_ylim(-1.1, 1.1)

ax2.plot(t, np.cos(t), 'b-')
ax2.set_title(r"$f(t)=\cos(t)$")
ax2.set_xlabel("$t$")
ax2.set_xlim(0, 2 * np.pi)
ax2.set_ylim(-1.1, 1.1)

fig.tight_layout()

3D Plots

In [28]:
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.gca(projection='3d')

theta = np.linspace(-4 * np.pi, 4 * np.pi, 200)
z = np.linspace(-2, 2, 200)

r = z**2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)

ax.plot(x, y, z, label='parametric curve')
ax.legend()

plt.show()

Weitere Beispiele zum 3dim Plotten findet ihr hier:

https://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html

LaTeX

Es ist auch möglich LaTeX für das Setzen aller Plot-Beschriftungen (d.h. Achsenbeschriftungen, Ticks, Legenden, usw.) zu verwenden. Seht Euch dazu die "TeX in matplotlib" Folien an.