Rheinwerk Computing < openbook >

 
Inhaltsverzeichnis
1 Einleitung
2 Die Programmiersprache Python
Teil I Einstieg in Python
3 Erste Schritte im interaktiven Modus
4 Der Weg zum ersten Programm
5 Kontrollstrukturen
6 Dateien
7 Das Laufzeitmodell
8 Funktionen, Methoden und Attribute
9 Informationsquellen zu Python
Teil II Datentypen
10 Das Nichts – NoneType
11 Operatoren
12 Numerische Datentypen
13 Sequenzielle Datentypen
14 Zuordnungen
15 Mengen
16 Collections
17 Datum und Zeit
18 Aufzählungstypen – Enum
Teil III Fortgeschrittene Programmiertechniken
19 Funktionen
20 Modularisierung
21 Objektorientierung
22 Ausnahmebehandlung
23 Iteratoren
24 Kontextobjekte
25 Manipulation von Funktionen und Methoden
Teil IV Die Standardbibliothek
26 Mathematik
27 Kryptografie
28 Reguläre Ausdrücke
29 Schnittstelle zu Betriebssystem und Laufzeitumgebung
30 Kommandozeilenparameter
31 Dateisystem
32 Parallele Programmierung
33 Datenspeicherung
34 Netzwerkkommunikation
35 Debugging und Qualitätssicherung
36 Dokumentation
Teil V Weiterführende Themen
37 Anbindung an andere Programmiersprachen
38 Distribution von Python-Projekten
39 Grafische Benutzeroberflächen
40 Python als serverseitige Programmiersprache im WWW – ein Einstieg in Django
41 Wissenschaftliches Rechnen
42 Insiderwissen
43 Von Python 2 nach Python 3
A Anhang
Stichwortverzeichnis

Download:
- Beispielprogramme, ca. 464 KB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Python 3 von Johannes Ernesti, Peter Kaiser
Das umfassende Handbuch
Buch: Python 3

Python 3
Pfeil 41 Wissenschaftliches Rechnen
Pfeil 41.1 Installation
Pfeil 41.2 Das Modellprogramm
Pfeil 41.2.1 Der Import von numpy, scipy und matplotlib
Pfeil 41.2.2 Vektorisierung und der Datentyp numpy.ndarray
Pfeil 41.2.3 Visualisieren von Daten mit matplotlib.pyplot
Pfeil 41.3 Überblick über die Module numpy und scipy
Pfeil 41.3.1 Überblick über den Datentyp numpy.ndarray
Pfeil 41.3.2 Überblick über scipy
 
Zum Seitenanfang

41.2    Das Modellprogramm Zur vorigen ÜberschriftZur nächsten Überschrift

Wir betrachten ein einfaches Modellprogramm, das zu einer Funktion ƒ(x) = x3 –10sin(x) – 4 die Ableitung und eine Stammfunktion numerisch berechnet und grafisch im Intervall [–3,3] darstellt. Anhand dieses Modellprogramms erläutern wir typische Vorgehensweisen beim Umgang mit numpy, scipy und matplotlib.

import numpy as np
import scipy as sp
import matplotlib as mpl
import matplotlib.pyplot as plt
import scipy.misc
import scipy.integrate
def f(x):
return x**3 - 10*np.sin(x) - 4
def df(x):
return sp.misc.derivative(f, x)
@np.vectorize
def F(x):
return sp.integrate.quad(f, 0, x)[0]
X = np.linspace(-3, 3, 200)
Y = f(X)
Y1 = df(X)
Y2 = F(X)
plt.plot(X, Y, linewidth=2, label="f")
plt.plot(X, Y1, linewidth=2, linestyle="dashed", label="f'")
plt.plot(X, Y2, linewidth=2, linestyle="dotted", label="F")
plt.legend()
plt.show()

Abbildung 41.1 zeigt die entstehende Grafik.

Die Funktion f mit Ableitung f’ und Stammfunktion F

Abbildung 41.1    Die Funktion f mit Ableitung f’ und Stammfunktion F

Dieses einfache Beispielprogramm zeigt bereits die wichtigsten Besonderheiten, die Sie bei der Arbeit mit numpy, scipy und matplotlib beachten sollten. Wir werden das Programm nun stückweise besprechen.

 
Zum Seitenanfang

41.2.1    Der Import von numpy, scipy und matplotlib Zur vorigen ÜberschriftZur nächsten Überschrift

In den ersten vier Zeilen werden die Module numpy, scipy und matplotlib importiert und mit Kurznamen versehen.

import numpy as np
import scipy as sp
import matplotlib as mpl
import matplotlib.pyplot as plt

Diese Art, die Module zu importieren, hat sich in der Praxis bewährt und wurde daher als Konvention eingeführt. Wir werden in den Beispielen in diesem Kapitel immer annehmen, dass die Module in dieser Weise importiert wurden, und empfehlen Ihnen, dieser Konvention auch in Ihren eigenen Programmen zu folgen.

Im Anschluss an die grundlegenden import-Anweisungen werden zusätzlich noch die Module scipy.misc und scipy.integrate geladen.

Da scipy sehr umfangreich ist, ist es nicht sinnvoll, dass jedes Programm alle Funktionen auf einmal importiert. Aus diesem Grund ist scipy in mehrere Pakete unterteilt, die bei Bedarf eingebunden werden müssen. In unserem Beispiel verwenden wir die Funktion derivative aus dem Paket scipy.misc zum Berechnen der Ableitung. Die Stammfunktion ermitteln wir mithilfe der Funktion quad aus dem Paket scipy.integrate.

Eine Übersichtstabelle über die Struktur von scipy finden Sie in Abschnitt 41.3.2.

 
Zum Seitenanfang

41.2.2    Vektorisierung und der Datentyp numpy.ndarray Zur vorigen ÜberschriftZur nächsten Überschrift

Nach den import-Anweisungen werden drei Funktionen f, df und F definiert, die die Funktion ƒ, ihre Ableitung ƒ’ und eine Stammfunktion F auswerten.

Für die Arbeit mit numpy und scipy ist es wichtig, dass die Funktionen f, df und F nicht nur für einzelne Zahlen, sondern für ganze Arrays von Zahlen funktionieren. Ein Array ist dabei eine geordnete Folge von gleichartigen Objekten, in der Regel von Zahlen. Bevor wir auf das Zusammenspiel von Arrays und Funktionen eingehen, besprechen wir kurz den elementaren Umgang mit Arrays.[ 228 ](Genaueres zum Umgang mit Arrays erfahren Sie später in Abschnitt 41.3.1. )

Um ein Array zu erzeugen, können Sie die Funktion numpy.array verwenden, der Sie zum Beispiel eine Liste mit den gewünschten Elementen des Arrays übergeben.

>>> a = np.array([0.5, 1, 2, 3])
>>> a
array([ 0.5, 1. , 2. , 3. ])

Das Besondere an Instanzen des Datentyps numpy.ndarray ist, dass mit ihnen wie mit Zahlen gerechnet werden kann. Die Operationen werden dabei elementweise durchgeführt.[ 229 ](Sind A ein zweidimensionales und x ein eindimensionales Array, bewirkt A*x keine Matrix-Vektor-Multiplikation, wie sie in der linearen Algebra üblich ist. Für die Matrix-Vektor-Multiplikation können Sie auf numpy.dot oder die Methode ndarray.dot zurückgreifen: np.dot(A,x) bzw. A.dot(x). Außerdem wurde in Python 3.5 der Operator @ eingeführt, sodass sich in neueren Python-Versionen anstelle von np.dot(A,x) auch A@x schreiben lässt. )

>>> a+a
array([ 1., 2., 4., 6.])
>>> a*a
array([ 0.25, 1. , 4. , 9. ])
>>> a**3
array([ 0.125, 1. , 8. , 27. ])
>>> 4*a
array([ 2., 4., 8., 12.])

Neben den Rechenoperationen können auch Funktionen auf Arrays angewendet werden, indem jedes Element des Arrays in die Funktion eingesetzt wird und die Ergebnisse als neues Array zusammengefasst werden.

Beispielsweise können wir die Funktion f aus unserem Beispielprogramm auf das Array a anwenden.

>>> f(a)
array([ -8.66925539, -11.41470985, -5.09297427, 21.58879992])

Hier werden die Werte ƒ(0.5), ƒ(1), ƒ(2) und ƒ(3) berechnet, in einem neuen Array abgelegt und zurückgegeben.

Dieses Prinzip, die gleiche Operation auf ein ganzes Array von Zahlen anzuwenden, nennt man Vektorisierung. Wenn eine Funktion außer Zahlen auch Arrays verarbeiten kann, wird sie als vektorisiert bezeichnet.

Die Funktionen des Moduls math der Python-Standard-Library wie beispielsweise sin, cos, tan oder exp sind nicht vektorisiert, weshalb numpy und scipy ihre eigenen vektorisierten Versionen dieser Funktionen mitbringen. In unserem Beispiel verwenden wir daher anstelle von math.sin die Funktion numpy.sin, die in der Lage ist, für ein Array von Zahlen die Sinuswerte zu berechnen.

Mit dem Wissen über Arrays und Vektorisierung können Sie die nächsten beiden Zeilen des Modellprogramms verstehen:

X = np.linspace(-3, 3, 100)
Y = f(X)

Zunächst generiert die Funktion numpy.linspace ein neues Array X, auf das anschließend die Funktion f elementweise angewendet wird. Die berechneten Funktionswerte werden im Array Y gespeichert.

Mithilfe von numpy.linspace kann ein Array mit einer bestimmten Anzahl von Elementen erzeugt werden, die alle den gleichen Abstand haben. Über die ersten beiden Parameter von numpy.linspace werden das größte und das kleinste Element des Arrays festgelegt. Der folgende Aufruf erzeugt beispielsweise ein Array mit fünf Elementen im Intervall von -1 bis 1.

>>> np.linspace(-1,1,5)
array([-1. , -0.5, 0. , 0.5, 1. ])

In unserem Modellprogramm wird also ein Array erzeugt, das 100 Zahlen aus dem Intervall von -3 bis 3 enthält und zu jeder dieser Zahlen den entsprechenden Wert der Funktion f berechnet.

Die folgende Zeile Y1 = df(X) bestimmt dann die Ableitung von f an den Stellen, die im Array X gespeichert sind. Bei der Definition von df nutzen wir aus, dass die Funktion scipy.misc.derivative vektorisiert ist und daher auch mit einem Array als Parameter funktioniert.

Vektorisieren nicht-vektorisierter Funktionen mittels numpy.vectorize

Wenn eine Funktion wie oben f oder df nur aus vektorisierten Operationen zusammengesetzt ist, ist auch das Ergebnis automatisch wieder vektorisiert. Es gibt allerdings auch Fälle, in denen die Vektorisierung nicht automatisch garantiert wird. Sie müssen sich jedoch nicht selbst Gedanken darüber machen, wie eine Funktion am besten vektorisiert werden kann, numpy bietet Ihnen dazu ein praktisches Hilfsmittel an.

Als Beispiel betrachten wir eine Funktion mit dem Namen clip_positive, die den Wert einer Zahl zurückgeben soll, wenn diese positiv ist, und 0, falls die Zahl einen negativen Wert hat. Eine mögliche Implementation dieser Funktion zeigt das folgende Listing:

>>> def clip_positive(x):
... if x > 0: return x
... else: return 0
>>> clip_positive(10)
10
>>> clip_positive(-5)
0
>>> clip_positive(2)
2

Wir möchten dieser Funktion auch Arrays als Wert für x übergeben, sodass ein neues Array erzeugt wird, das für positive Einträge von x den Eintrag selbst und für negative Einträge den Wert 0 enthält. So wie die Funktion jetzt implementiert ist, funktioniert sie jedoch nicht für Arrays, da sich die Fallunterscheidung in dieser Form nicht auf Arrays übertragen lässt.

Abhilfe schafft der Function Decorator[ 230 ](Näheres über die Verwendung der Function Decorator erfahren Sie im Abschnitt 25.1. ) numpy.vectorize, der eine Funktion so anpasst, dass sie neben einzelnen Zahlen auch Arrays als Parameter akzeptiert.

>>> @np.vectorize
... def clip_positive(x):
... if x > 0: return x
... else: return 0
>>> clip_positive(10)
array(10)
>>> clip_positive(-5)
array(0)
>>> b = np.array([4, -3, 0.7, -10, 8])
>>> clip_positive(b)
array([ 4. , 0. , 0.7, 0. , 8. ])

Wie Sie sehen, funktioniert die Funktion clip_positive nun sowohl mit einzelnen Zahlen als auch mit ganzen Arrays als Parametern. Allerdings wird jetzt auch dann ein Array erzeugt, wenn für den Parameter x eine Zahl übergeben wurde. Dies ist deshalb kein Problem, weil sich Arrays der Länge 1 wie Zahlen verhalten und daher auch in weiteren Berechnungen wie solche verwendet werden können.

Mit diesem Wissen können wir die Implementation der Funktion F in unserem Modellprogramm verstehen. Das folgende Listing wiederholt die Definition aus dem Programm.

@np.vectorize
def F(x):
return sp.integrate.quad(f, 0, x)[0]

Die Funktion scipy.integrate.quad erwartet als ersten Parameter die zu integrierende Funktion. Mit den beiden folgenden Parametern werden die Integrationsgrenzen angegeben. Der Rückgabewert von scipy.integrate.quad ist ein Tupel, bestehend aus zwei Elementen, wobei der erste Eintrag eine Näherung des Integrals und der zweite Eintrag eine obere Schranke für den Approximationsfehler darstellt.

>>> sp.integrate.quad(f, 0, 4)
(31.463563791363885, 7.668063971742951e-13)

Die Funktion F liefert somit für ein x das Integral über f von 0 bis x, also

inline image

Sie ist damit nach dem Hauptsatz der Differenzial- und Integralrechnung eine Stammfunktion von f. Durch den Function Decorator numpy.vectorize wird die Funktion für die Verwendung von Arrays als Parameterwerten erweitert.

Die Zeile Y2 = F(X) des Modellprogramms bestimmt die Werte einer Stammfunktion von f an den Stellen, die im Array X gespeichert sind.

[»]  Hinweis

Die vektorisierten Funktionen von numpy und scipy sind hardwarenah implementiert und dadurch sehr effizient. Wenn Sie eine Funktion mittels numpy.vectorize vektorisieren, geht dieser Geschwindigkeitsvorteil verloren.

Sie sollten daher versuchen, bei laufzeitkritischen Funktionen soweit möglich auf die schnellen Routinen von numpy und scipy zurückzugreifen.

 
Zum Seitenanfang

41.2.3    Visualisieren von Daten mit matplotlib.pyplot Zur vorigen ÜberschriftZur nächsten Überschrift

Nachdem nun die gewünschten Daten berechnet wurden, möchten wir sie grafisch darstellen. Wir verwenden dazu das Modul matplotlib.pyplot, das an die Zeichenschnittstelle von MATLAB angelehnt ist.

Sie können sich diese Schnittstelle wie ein leeres Blatt Papier vorstellen, zu dem durch Aufrufe von Funktionen aus dem Modul matplotlib.pyplot neue grafische Elemente hinzugefügt werden. Ist das Zeichnen beendet, wird das Ergebnis mit der Funktion matplotlib.pyplot.show auf dem Bildschirm angezeigt.

Die wichtigste Funktion ist matplotlib.pyplot.plot, mit der sich beliebige Daten visualisieren lassen. Im einfachsten Fall übergeben Sie der Funktion plot eine Liste von Zahlen.

>>> plt.plot([1, 3, 5, 2, 1, 4, 6, 7, 3])
[<matplotlib.lines.Line2D object at 0x7f3c5e0947f0>]
>>> plt.show()

Diese Zahlen werden nun als Funktionswerte aufgefasst, wobei die Indizes der Liste, also 0, 1, 2, …, 8, als zugehörige Werte auf der x-Achse interpretiert werden. Zwischen den angegebenen Funktionswerten wird linear interpoliert, sodass die einzelnen Datenpunkte durch gerade Linien miteinander verbunden werden.

Abbildung 41.2 veranschaulicht das Ergebnis.

Ein einfacher Plot einer Liste von Zahlen

Abbildung 41.2    Ein einfacher Plot einer Liste von Zahlen

Die Werkzeugleiste am oberen Rand des Fensters bietet eine Reihe von Operationen, um die Grafik zu verändern. Außerdem kann die Grafik in verschiedenen Grafikformaten (beispielsweise PNG, PS, EPS, PDF, SVG) gespeichert werden.

In der Regel möchten Sie die Werte auf der x-Achse, die zu den Funktionswerten gehören, explizit angeben und nicht automatisch über die Indizes ermitteln lassen. Dazu übergeben Sie der Funktion plot zwei Listen oder Arrays, wobei der erste Parameter die x-Werte und der zweite Parameter die zugehörigen y-Werte enthält.

Um beispielsweise eine Periode der Sinusfunktion zu zeichnen, erzeugen wir mit numpy.linspace zunächst ein Array, das Datenpunkte im Intervall [0,2π] enthält, und wenden anschließend die Funktion numpy.sin darauf an. Die Ergebnisse geben wir dann an plot weiter.

>>> X = np.linspace(0, 2*np.pi, 200)
>>> Y = np.sin(X)
>>> plt.plot(X, Y)
[<matplotlib.lines.Line2D object at 0x7f3c5d495e80>]
>>> plt.show()

Das Resultat ist in Abbildung 41.3 dargestellt.

Plot der Sinusfunktion

Abbildung 41.3    Plot der Sinusfunktion

Möchten Sie mehrere Funktionen in einer Grafik darstellen, können Sie plot mehrmals aufrufen, bevor das Ergebnis mittels show angezeigt wird, wie dies auch in unserem Modellprogramm gemacht wird.

Über zusätzliche Parameter der Funktion plot kann das Aussehen der Grafik angepasst werden. Das folgende Listing zeigt die Befehle, mit denen in unserem Modellprogramm die grafische Ausgabe erzeugt wird. Dabei verwenden wir den Parameter linewidth, um die Dicke der Linien anzupassen, und verändern über linestyle das Aussehen der Linien. Mit dem Parameter label kann jedem Plot eine Zeichenfolge zugeordnet werden, die in der Legende des Plots angezeigt wird. Der Aufruf der Funktion legend sorgt dafür, dass die Legende sichtbar wird.

plt.plot(X, Y, linewidth=2, label="f")
plt.plot(X, Y1, linewidth=2, linestyle="dashed", label="f'")
plt.plot(X, Y2, linewidth=2, linestyle="dotted", label="F")
plt.legend()
plt.show()

In Abbildung 41.4 ist das Ausgabefenster des Modellprogramms dargestellt.

Endgültige Ausgabe des Modellprogramms

Abbildung 41.4    Endgültige Ausgabe des Modellprogramms

Das Modul matplotlib ist in der Lage, komplexe 2-D- und 3-D-Visualisierungen zu erzeugen und zu gestalten. Insbesondere verfügt es über umfangreiche Exportmöglichkeiten, um die Visualisierungen beispielsweise in wissenschaftlichen Arbeiten zu verwenden.

Die verfügbaren Möglichkeiten gehen weit über den hier präsentierten Einstieg hinaus. Wir verweisen Sie für weitere Informationen auf die Onlinedokumentation auf der Seite http://www.matplotlib.org.

 


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Python 3 Python 3
Jetzt Buch bestellen

 Buchempfehlungen
Zum Rheinwerk-Shop: Einstieg in Python
Einstieg in Python


Zum Rheinwerk-Shop: Python. Der Grundkurs
Python. Der Grundkurs


Zum Rheinwerk-Shop: Algorithmen mit Python
Algorithmen mit Python


Zum Rheinwerk-Shop: Objektorientierte Programmierung
Objektorientierte Programmierung


Zum Rheinwerk-Shop: Raspberry Pi. Das umfassende Handbuch
Raspberry Pi. Das umfassende Handbuch


Zum Rheinwerk-Shop: Roboter-Autos mit dem Raspberry Pi
Roboter-Autos mit dem Raspberry Pi


Zum Rheinwerk-Shop: Neuronale Netze programmieren mit Python
Neuronale Netze programmieren mit Python


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2020
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern