Numpy

  • Meist hat man nach in einer Auswertung Datenpunkte, die verarbeitet werden müssen
  • Numpy ist eine Python-Bibliothek, die den Umgang mit Datenpunkten enorm vereinfacht
In [1]:
import numpy as np
  • Grunddatentyp von Numpy: das Array
  • Kann man sich als effizientere Liste vorstellen
  • Idee von Numpy: Man kann ein Array ähnlich wie eine Zahl verwenden. Operationen werden dann auf allen Elementen ausgeführt
  • Am besten versteht man das mit einigen Beispielen:
In [2]:
# Listen können mittels np.array in Arrays konvertiert werden
x = np.array([1, 2, 3, 4, 5])
In [3]:
2 * x
# x + x
Out[3]:
array([ 2,  4,  6,  8, 10])
In [4]:
x**2
Out[4]:
array([ 1,  4,  9, 16, 25])
In [5]:
x**x
Out[5]:
array([   1,    4,   27,  256, 3125])
In [6]:
np.cos(x)
Out[6]:
array([ 0.54030231, -0.41614684, -0.9899925 , -0.65364362,  0.28366219])

Achtung: Man braucht das cos aus numpy!

In [7]:
import math
#math.cos(x)

Funktionen, die nur für eine Zahl geschrieben wurden, funktionieren oft ohne Änderung mit Arrays!

In [8]:
def poly(y):
    return y + 2 * y**2 - y**3

poly(x)
Out[8]:
array([  2,   2,  -6, -28, -70])

Das erlaubt es einem unter anderem sehr leicht physikalische Formeln auf seine Datenpunkte anzuwenden.

Arrays können beliebige Dimension haben:

In [9]:
# zweidimensionales Array
y = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

y + y
Out[9]:
array([[ 2,  4,  6],
       [ 8, 10, 12],
       [14, 16, 18]])

Das erlaubt es z.B. eine ganze Tabelle als ein Array abzuspeichern.

Es gibt viele nützliche Funktionen, die bei der Erstellung von Arrays helfen:

In [10]:
np.zeros(10)
Out[10]:
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])
In [11]:
np.ones(5)
Out[11]:
array([ 1.,  1.,  1.,  1.,  1.])
In [12]:
np.linspace(0, 1, 11)
Out[12]:
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])
In [13]:
# wie range() für arrays:
np.arange(0, 10)
Out[13]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Numpy Indexing

Numpy erlaubt einem sehr bequem bestimmte Elemente aus einem Array auszuwählen

In [14]:
x = np.arange(0, 10)

# kennen wir schon:
x[4]
Out[14]:
4
In [15]:
# alle Elemente mit Index 1 bis 3:
x[1:4]
Out[15]:
array([1, 2, 3])
In [16]:
# negative Indizes zählen vom Ende des Arrays:
x[-1], x[-2]
Out[16]:
(9, 8)
In [17]:
# Kombination aus beiden:
x[3:-2]
Out[17]:
array([3, 4, 5, 6, 7])
In [18]:
# man kann eine Schrittgröße angeben
x[::2]
Out[18]:
array([0, 2, 4, 6, 8])
In [19]:
# Trick zum Umkehren: negative Schrittgröße
x[::-1]
Out[19]:
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
In [20]:
y = np.array([x, x + 10, x + 20, x + 30])
y
Out[20]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39]])
In [21]:
# mehrere Indizes mit Kommas getrennt:
y[3, 2:-1]
Out[21]:
array([32, 33, 34, 35, 36, 37, 38])
In [22]:
# Oder man gibt nur einen Index an ⇒ eindimensionales Array
y[2]
Out[22]:
array([20, 21, 22, 23, 24, 25, 26, 27, 28, 29])

Masken

Oft will man Elemente auswählen, die eine bestimmte Bedingung erfüllen.

Hierzu erstellt man zuerst eine Maske (Arrays aus True/False-Werten).

Diese kann man in eckigen Klammern übergeben.

In [23]:
a = np.linspace(0, 2, 11)
b = a**2

a[a>=1]
#a[b==a]
#a[b>a]
Out[23]:
array([ 1. ,  1.2,  1.4,  1.6,  1.8,  2. ])

Reduzieren von Arrays

Viele Rechenoperationen reduzieren ein Array auf einen einzelnen Wert

In [24]:
x
Out[24]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [25]:
np.sum(x)
Out[25]:
45
In [26]:
np.prod(x)
Out[26]:
0
In [27]:
np.mean(x)
Out[27]:
4.5
In [28]:
# Standardabweichung:
np.std(x)
Out[28]:
2.8722813232690143
In [29]:
# Fehler des Mittelwerts (geht auch einfacher):
np.std(x) / np.sqrt(len(x))
Out[29]:
0.90829510622924747
In [30]:
# Differenzen zwischen benachbarten Elementen
np.diff(x**2)
Out[30]:
array([ 1,  3,  5,  7,  9, 11, 13, 15, 17])

Input / Output

Einlesen aus Textdateien: genfromtxt

Sie gibt den Inhalt einer Textdatei als Array zurück.

Das Gegenstück ist savetxt.

In [31]:
n = np.arange(11)
x = np.linspace(0, 1, 11)

np.savetxt('test.txt', [n, x])
print(open('test.txt', 'r').read())
0.000000000000000000e+00 1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00 4.000000000000000000e+00 5.000000000000000000e+00 6.000000000000000000e+00 7.000000000000000000e+00 8.000000000000000000e+00 9.000000000000000000e+00 1.000000000000000000e+01
0.000000000000000000e+00 1.000000000000000056e-01 2.000000000000000111e-01 3.000000000000000444e-01 4.000000000000000222e-01 5.000000000000000000e-01 6.000000000000000888e-01 7.000000000000000666e-01 8.000000000000000444e-01 9.000000000000000222e-01 1.000000000000000000e+00


Man sollte aber immer erklären, was man da abspeichert:

In [32]:
n = np.arange(11)
x = np.linspace(0, 1, 11)

# header schreibt eine Kommentarzeile in die erste Zeile der Datei
np.savetxt('test.txt', [n, x], header="n \t x")
print(open('test.txt', 'r').read())
# n 	 x
0.000000000000000000e+00 1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00 4.000000000000000000e+00 5.000000000000000000e+00 6.000000000000000000e+00 7.000000000000000000e+00 8.000000000000000000e+00 9.000000000000000000e+00 1.000000000000000000e+01
0.000000000000000000e+00 1.000000000000000056e-01 2.000000000000000111e-01 3.000000000000000444e-01 4.000000000000000222e-01 5.000000000000000000e-01 6.000000000000000888e-01 7.000000000000000666e-01 8.000000000000000444e-01 9.000000000000000222e-01 1.000000000000000000e+00


Einlesen der Werte mit genfromtxt :

In [33]:
a, b = np.genfromtxt('test.txt')

print(a)
print(b)
[  0.   1.   2.   3.   4.   5.   6.   7.   8.   9.  10.]
[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1. ]

Oft schreibt man seine Datenpunkte aber spaltenweise:

1  1
2  4
3  9
4 16
5 20

Dann kann man unpack=True verwenden, um die Daten zu transponieren. Um die Daten entsprechend transponiert zu speichern, verwenden wir

In [34]:
np.savetxt('test_T.txt', np.array([n, x]).T)
print(open('test_T.txt', 'r').read())
0.000000000000000000e+00 0.000000000000000000e+00
1.000000000000000000e+00 1.000000000000000056e-01
2.000000000000000000e+00 2.000000000000000111e-01
3.000000000000000000e+00 3.000000000000000444e-01
4.000000000000000000e+00 4.000000000000000222e-01
5.000000000000000000e+00 5.000000000000000000e-01
6.000000000000000000e+00 6.000000000000000888e-01
7.000000000000000000e+00 7.000000000000000666e-01
8.000000000000000000e+00 8.000000000000000444e-01
9.000000000000000000e+00 9.000000000000000222e-01
1.000000000000000000e+01 1.000000000000000000e+00


SciPy

SciPy

SciPy

  • Baut auf Numpy auf
  • Kann numerisch integrieren, DGLs lösen, optimieren, minimieren, …
  • Enthält auch physikalische Konstanten und wichtige mathematische Funktionen
In [35]:
# Fehler des Mittelwerts:
from scipy.stats import sem # standard error of mean
sem(x)
Out[35]:
0.10000000000000002
In [36]:
# Physikalische Konstanten:
import scipy.constants as const
const.epsilon_0
Out[36]:
8.854187817620389e-12
In [37]:
# Temperaturen konvertieren:
const.C2K(100), const.K2C(100)
Out[37]:
(373.14999999999998, -173.14999999999998)
In [38]:
# Winkel konvertieren:
np.degrees(np.pi), np.radians(90)
Out[38]:
(180.0, 1.5707963267948966)
In [39]:
# noch mehr Konstanten (mit Einheit und Fehler)!
list(const.physical_constants.items())[:10]
Out[39]:
[('electron-triton mass ratio', (0.00018192000653, '', 1.7e-13)),
 ('proton mass in u', (1.007276466812, 'u', 9e-11)),
 ('muon mass in u', (0.1134289267, 'u', 2.9e-09)),
 ('neutron-proton mass difference in u', (0.00138844919, '', 4.5e-10)),
 ('shielded proton magn. moment to Bohr magneton ratio',
  (0.001520993132, '', 1.6e-11)),
 ('nuclear magneton in eV/T', (3.1524512605e-08, 'eV T^-1', 2.2e-17)),
 ('Faraday constant for conventional electric current',
  (96485.3321, 'C_90 mol^-1', 0.0043)),
 ('neutron-proton mass difference energy equivalent',
  (2.0721465e-13, '', 6.8e-20)),
 ('shielded helion magn. moment', (-1.074553024e-26, 'J T^-1', 9.3e-34)),
 ('tau molar mass', (0.00190749, 'kg mol^-1', 1.7e-07))]

Achtung

Wenn solche Konstanten genutzt werden, muss das korrekt mitgeteilt, also zitiert werden. Darauf gehen wir nächste Woche im LaTeX-Workshop ein :-)

(Quelle hier: python-scipy)

In [40]:
# physical_constants ist ein dict in dem hinter keys 
# Wert, Einheit und Fehler hinterlegt sind

const.physical_constants["proton mass"]
Out[40]:
(1.672621777e-27, 'kg', 7.4e-35)

Fitten

Oft möchte man eine Funktion, zum Beispiel eine Erwartung aus der Theorie, an die gemessenen Werte anpassen. Dies nennt man Fit.

In [41]:
# Beliebige Funktionen fitten
%matplotlib inline
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (10, 8)
plt.rcParams['font.size'] = 16

x, y = np.genfromtxt('example_data.txt', unpack=True)

def f(x, a, b):
    return a * x + b

params, covariance = curve_fit(f, x, y)
# covariance ist die Kovarianzmatrix

errors = np.sqrt(np.diag(covariance))

print('a =', params[0], '±', errors[0])
print('b =', params[1], '±', errors[1])

x_plot = np.linspace(0, 10)

plt.plot(x, y, 'rx', label="example data")
plt.plot(x_plot, f(x_plot, *params), 'b-', label='linearer Fit')
plt.legend(loc="best")
a = 4.97742635551 ± 0.0214390034102
b = 0.070084504726 ± 0.123809150457

Out[41]:
<matplotlib.legend.Legend at 0x7f84ef425b00>