Datenvisualisierung mit¶

Matplotlib

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 den kürzeren Namen plt.

In [1]:
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 der Einfachheit halber ein paar Funktion aus numpy, die euch schon bekannt sind.

In [2]:
import numpy as np

Zu erst ein einfaches Beispiel mit $f(x)=x^2$

In [3]:
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()

Um den Text-Output zu unterdrücken in diesem Notebook, schreiben wir ein ; hinter die letzte Zeile.

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

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));
In [6]:
plt.plot(t, np.sin(t), 'r--');
In [7]:
plt.plot(t, np.sin(t), 'go');

Tabelle mit allen Farben und Stilen: 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);

Es fehlt noch etwas...¶

(http://imgs.xkcd.com/comics/convincing.png)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.

Einheiten in Achsenbeschriftungen werden wegdividiert:¶

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}$');

plt.plot(t, np.sin(t))
plt.xlabel(r'$t / \mathrm{s}$')
plt.ylabel(r'$U \,/\, \mathrm{V}$');  # Spaces sind Geschmacksfrage

Mehr zu Einheiten gibt es im LaTeX-Kurs.

Legende¶

Legenden für Objekte die ein label tragen

In [11]:
plt.plot(t, np.sin(t), label=r'$\sin(t)$')
plt.legend();
#plt.legend(loc='lower left')
#plt.legend(loc='best')

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 [12]:
plt.plot(t, np.sin(t))
plt.grid();

Laden von Daten¶

In [13]:
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-');

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 [14]:
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 [15]:
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 [16]:
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();

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

Man kann auch mehrere Plots in ein Bild packen:

In [17]:
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);

Dies führt manchmal zu Spacing-Problemen und Teilen die sich überschneiden.

Beispiel

Lösung: constrained_layout=True

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

plt.subplots(constrained_layout=True)

# Anzahl Zeile, Anzahl Spalten, Nummer des Plots
plt.figure(constrained_layout=True)

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)$");

Plot im Plot:

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

plt.plot(x, x**2)

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

plt.plot(x, x**3);

Plots mit Fehlerbalken¶

Sehr häufig werden im Praktikum Plots mit Fehlerbalken benötigt, hier erzeugen wir einfach zufällige Fehlerbalken:

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

plt.errorbar(x + errX, x + errY, xerr=errX, yerr=errY, fmt='o');

Achsen-Skalierung¶

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

In [21]:
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 [22]:
#r = np.linspace(0, 10, 1000)
r = np.linspace(0, 10, 50)
theta = 2 * np.pi * r

plt.polar(theta, r);

Ticks¶

Man kann sehr viele Sachen mit Ticks machen…

In [23]:
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!");
In [24]:
months = ['Januar',
          'Februar',
          'März',
          'April',
          'Mai',
          'Juni',
          'Juli',
          'August',
          'September',
          'Oktober',
          'November',
          'Dezember']

plt.plot(np.arange(12), np.random.random(12))
plt.xticks(np.arange(12), months, rotation=45, rotation_mode='anchor', ha='right', va='top')
plt.xlim(0, 11);

Histogramme¶

Sehr häufig braucht man Histogramme.

In [25]:
# Zufallsdaten generieren:
x = np.random.normal(0, 1, 1000)
plt.hist(x, bins=20);
# try histtype='stepfilled'

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 [26]:
import matplotlib.pyplot as plt
import numpy as np

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

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

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);

3D Plots¶

In [27]:
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(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();

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.