Wissenschaftliches Python Tutorial

Nachdem wir uns im Python Tutorial um die Grundlagen gekümmert haben, wollen wir uns nun mit einigen Bibliotheken beschäftigen, die das wissenschaftliche Arbeiten erleichtern. Diese sind

  • Numpy für effiziente Berechnungen auf strukturierten Daten
  • Matplotlib bietet eine einfache Möglichkeit Daten schön darzustellen
  • Scipy enthält mathematische Funktionen und Algorithmen für statistische Berechnungen, Fits, etc.

Zunächst laden wir die Bibliotheken. Sollte dabei ein Fehler auftreten, stell bitte sicher, dass bei der Installation alles geklappt hat und du kein Paket vergessen hast. Die erste Zeile mit dem %-Zeichen ist sogenannte "Magie", die dafür sorgt, dass Plots im Notebook dargestellt werden.


In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import scipy

Numpy: Arrays und effiziente Berechnungen

Das Herzstück von Numpy ist das Array. Dieser Datentyp repräsentiert eine Matrix und ist unter der Haube in C implementiert. Dabei wird großer Wert auf effiziente Speichernutzung gelegt. Der gängige Satz "Python ist viel zu langsam" ist also nicht zwingend wahr. Wir können Arrays auf verschiedene Arten erzeugen.


In [2]:
xs = np.array([1, 2, 3, 4])  # Konvertiert eine Python-Liste in ein Numpy-Array
print(xs)
ys = np.arange(4)  # Erzeugt ein Array analog zur `range` Funktion
print(ys)


[1 2 3 4]
[0 1 2 3]

Numpy Arrays unterstützen arithmetische Operationen, die wiederum effizient implementiert sind. Beispielsweise lassen sich zwei Arrays (elementweise) addieren sofern sie die gleichen Dimensionen haben.


In [3]:
xs + ys


Out[3]:
array([1, 3, 5, 7])

Um einen Überblick über alle Features von Numpy zu bekommen, können wir die Hilfe zu Rate ziehen. Zusätzlich zur help Funktion bietet IPython auch die ?-Magie mit einer besseren Integration in Jupyter


In [4]:
np?

Für die Übungsaufgaben werden wir häufig Zufallszahlen brauchen. Dafür bietet sich die Verwendung von np.random an.


In [5]:
np.random?

In [6]:
n_events = 10000
gauss = np.random.normal(2, 3, size=n_events)  # Erzeuge 10000 Gauß-verteilte Zufallszahlen
                                               # mit µ=2 und σ=3.

Matplotlib: Schöne Plots

Matplotlib bietet sehr intuitive Funktionen um Daten darzustellen. Die sehr ausführliche Dokumentation bietet einen guten Überblick. Wir benutzen an dieser Stelle nur das pyplot Submodul, das uns ein einfaches Interface für die Kernfunktionalität bietet. In der Matplotlib Galerie finden sich viele schöne Beispiele mit Codeschnipseln.

Um unsere Gauß-verteilten Zufallszahlen zu histogrammieren benutzen wir einfach plt.hist. Außerdem setzen wir gleich Achsenbeschriftungen.


In [7]:
plt.hist(gauss)
plt.xlabel('Wert')
plt.ylabel('Absolute Häufigkeit')


Out[7]:
<matplotlib.text.Text at 0x10bb5b860>

Falls dir dieser Plot zu steril ist, können wir den Stil der bekannten R-Bibliothek ggplot2 verwenden.


In [8]:
plt.style.use('ggplot')

Wir wollen nun die Anzahl Bins erhöhen und zusätzlich das Histogramm normieren, damit wir die normierte Verteilungsfunktion (PDF) eintragen können.


In [9]:
plt.hist(gauss, bins=20, normed=True)
plt.xlabel('Wert')
plt.ylabel('Relative Häufigkeit')


Out[9]:
<matplotlib.text.Text at 0x10bc9cd30>

Scipy: Statistische Funktionen und mehr

Die PDF erhalten wir ebenfalls aus Scipy. Um sie plotten zu können, müssen wir sie auf eine Reihe von Werten anwenden um Datenpunkte zu erhalten. Hier zeigt sich erneut die Stärke von Numpy: wir können einfach die Funktion auf das ganze Array anwenden und erhalten ein Array von Ergebnissen. Scipy ist modular aufgebaut, so dass wir mit unserem obigen Import nicht alle Untermodule enthalten. Wir müssen das Statistikmodul explizit importieren.


In [12]:
import scipy.stats
pdf = scipy.stats.norm(2, 3).pdf
xs = np.linspace(-15, 15, 5000)  # Erzeuge 5000 äquidistante Werte im Interval [-15, 15).

plt.hist(gauss, bins=20, normed=True, label='Werte')
plt.plot(xs, pdf(xs), label='PDF')
plt.xlabel('Wert')
plt.ylabel('Relative Häufigkeit')
plt.legend()


Out[12]:
<matplotlib.legend.Legend at 0x10d5854e0>

Das sieht doch schon mal hübsch aus. Zum Abschluss wollen wir noch Unsicherheiten auf die Bins berechnen und in das Histogramm eintragen. Um es einfach zu halten, verwenden wir nicht die normierte PDF, sondern skalieren unsere PDF auf unsere Daten.


In [19]:
bins, edges = np.histogram(gauss, bins=20)
bin_width = edges[1] - edges[0]  # Alle Bins haben die gleiche Breite
centres = edges[:-1] + bin_width / 2

def scaled_pdf(x):
    return bin_width * n_events * pdf(x)

plt.errorbar(  # Typisches "Teilchenphysikerhistorgamm"
    centres,  # x
    bins,  # y
    xerr=bin_width/2,  # Unsicherheit auf x: hier Breite der Bins
    yerr=np.sqrt(bins),  # Unsicherheit auf y
    fmt='o',  # Benutze Punkte statt Linien zur Darstellung
    label='Data'
)
plt.plot(xs, scaled_pdf(xs), label='PDF')
plt.xlabel('Wert')
plt.ylabel('Relative Häufigkeit')
plt.ylim(-100, 2000)  # Manuelles Setzen des sichtbaren vertikalen Ausschnittes
plt.legend()


Out[19]:
<matplotlib.legend.Legend at 0x10dd0cba8>

Ich denke das ist ein guter Punkt um unsere kleine Einführung zu beenden.

An dieser Stelle sei abschließend auf die Scipy Dokumentation verwiesen. Neben dem Statistikmodul gibt es dort Funktionen für, unter anderem, Integration (scipy.integrate), Optimierung/Fits (scipy.optimize), Interpolation (scipy.interpolate), Fouriertransformationen (scipy.fftpack) und viele mehr.

Weiterführendes Material

  • Pandas ein mächtiges Werkzeug für die Analyse tabellarischer Daten im Stile von Data Frames in R
  • Uncertainties Bibliothek für das Rechnen mit Unsicherheiten
  • SimPy Bibliothek für symbolisches Rechnen