Handbuch Data Science mit Python - Jake VanderPlas - E-Book

Handbuch Data Science mit Python E-Book

Jake VanderPlas

0,0

Beschreibung

Der unverzichtbare Werkzeugkasten für Data Science in der 2. Auflage - Das bewährte Standardwerk jetzt in vollständig aktualisierter Neuauflage - Behandelt die neuesten Versionen von IPython, NumPy, pandas, Matplotlib und Scikit-Learn - Die leicht nachvollziehbaren Beispiele helfen Ihnen bei der erfolgreichen Einrichtung und Nutzung der Data-Science-Tools - Inklusive Jupyter Notebooks, die es Ihnen ermöglichen, den Code direkt beim Lesen auszuprobieren Für viele Data Scientists ist Python die Sprache der Wahl, weil zahlreiche ausgereifte Bibliotheken zum Speichern, Bearbeiten und Auswerten von Daten verfügbar sind. Jake VanderPlas versammelt in dieser 2. Auflage seines Standardwerks alle wichtigen Datenanalyse Tools in einem Band und erläutert deren Einsatz in der Praxis. Beschrieben werden IPython, Jupyter, NumPy, Pandas, Matplotlib, Scikit Learn und verwandte Werkzeuge. Für Datenanalystinnen und analysten und Data Cruncher mit Python Kenntnissen ist dieses umfassende Handbuch von unschätzbarem Wert bei der Erledigung ihrer täglichen Aufgaben. Dazu gehören die Manipulation, Umwandlung und Bereinigung von Daten, die Visualisierung verschiedener Datentypen sowie die Nutzung von Daten zum Erstellen von Statistiken und Machine Learning Modellen. Dieses Handbuch beschreibt die folgenden Tools: - IPython und Jupyter bieten eine Umgebung für Berechnungen, die von vielen Data Scientists genutzt wird - NumPy stellt das ndarray zum effizienten Speichern und Bearbeiten dicht gepackter Datenarrays bereit - Pandas verfügt über das DataFrameObjekt für die Speicherung und Manipulation gelabelter und spaltenorientierter Daten - Matplotlib ermöglicht die flexible und vielseitige Visualisierung von Daten - ScikitLearn unterstützt bei der Implementierung der wichtigsten und gebräuchlichsten Algorithmen für das Machine Learning »Jake beschreibt weit mehr als die Grundlagen dieser Open-Source-Tools; er erläutert die zugrunde liegenden Konzepte, Vorgehensweisen und Abstraktionen in klarer Sprache und mit verständlichen Erklärungen.« -- Brian Granger, Physikprofessor und Mitbegründer des Jupyter-Projekts

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 587

Veröffentlichungsjahr: 2023

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Copyright und Urheberrechte:

Die durch die dpunkt.verlag GmbH vertriebenen digitalen Inhalte sind urheberrechtlich geschützt. Der Nutzer verpflichtet sich, die Urheberrechte anzuerkennen und einzuhalten. Es werden keine Urheber-, Nutzungs- und sonstigen Schutzrechte an den Inhalten auf den Nutzer übertragen. Der Nutzer ist nur berechtigt, den abgerufenen Inhalt zu eigenen Zwecken zu nutzen. Er ist nicht berechtigt, den Inhalt im Internet, in Intranets, in Extranets oder sonst wie Dritten zur Verwertung zur Verfügung zu stellen. Eine öffentliche Wiedergabe oder sonstige Weiterveröffentlichung und eine gewerbliche Vervielfältigung der Inhalte wird ausdrücklich ausgeschlossen. Der Nutzer darf Urheberrechtsvermerke, Markenzeichen und andere Rechtsvorbehalte im abgerufenen Inhalt nicht entfernen.

Handbuch Data Science mit Python

Grundlegende Tools für die Arbeit mit Daten

Jake VanderPlas

Deutsche Übersetzung von Knut Lorenzen und Jørgen W. Lang

Jake VanderPlas

Lektorat: Alexandra Follenius

Übersetzung: Knut Lorenzen, Jørgen W. Lang

Copy-Editing: Sibylle Feldmann, www.richtiger-text.de

Satz: III-satz, www.drei-satz.de

Herstellung: Stefanie Weidner

Umschlaggestaltung: Karen Montgomery, Michael Oréal, www.oreal.de

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

ISBN:

Print     978-3-96009-225-4

PDF      978-3-96010-812-2

ePub     978-3-96010-813-9

mobi     978-3-96010-814-6

1. Auflage 2024

Translation Copyright für die deutschsprachige Ausgabe © 2024 dpunkt.verlag GmbH

Wieblinger Weg 17

69123 Heidelberg

Authorized German translation of the English edition of Python Data Science Handbook, 2nd Edition, ISBN 9781098121228 © 2023 Jake VanderPlas. This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same.

Dieses Buch erscheint in Kooperation mit O’Reilly Media, Inc. unter dem Imprint »O’REILLY«. O’REILLY ist ein Markenzeichen und eine eingetragene Marke von O’Reilly Media, Inc. und wird mit Einwilligung des Eigentümers verwendet.

Hinweis:

Dieses Buch wurde mit mineralölfreien Farben auf PEFC-zertifiziertem Papier aus nachhaltiger Waldwirtschaft gedruckt. Der Umwelt zuliebe verzichten wir zusätzlich auf die Einschweißfolie. Hergestellt in Deutschland.

Schreiben Sie uns:

Falls Sie Anregungen, Wünsche und Kommentare haben, lassen Sie es uns wissen: [email protected].

Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.

Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.

Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Übersetzer noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.

5 4 3 2 1 0

Inhalt

Einleitung

Teil I: Mehr als normales Python: Jupyter

1Der Einstieg in IPython und Jupyter

Die IPython-Shell starten

Das Jupyter Notebook starten

Hilfe und Dokumentation in IPython

Tastaturkürzel in der IPython-Shell

2Erweiterte interaktive Features

Magische Befehle in IPython

Verlauf der Ein- und Ausgabe

IPython und Shell-Befehle

3Debugging und Profiling

Fehler und Debugging

Profiling und Timing von Code

Weitere IPython-Ressourcen

Teil II: Einführung in NumPy

4Die Datentypen in Python

Python-Integer sind mehr als nur ganzzahlige Werte

Python-Listen sind mehr als nur einfache Listen

Arrays feststehenden Typs in Python

Arrays anhand von Listen erzeugen

Neue Arrays erzeugen

NumPys Standarddatentypen

5Grundlagen von NumPy-Arrays

Attribute von NumPy-Arrays

Indizierung von Arrays: Zugriff auf einzelne Elemente

Slicing: Teilmengen eines Arrays auswählen

Arrays umformen

Arrays verketten und aufteilen

6Berechnungen mit NumPy-Arrays: universelle Funktionen

Langsame Schleifen

Kurz vorgestellt: UFuncs

NumPys UFuncs im Detail

UFunc-Features für Fortgeschrittene

UFuncs: mehr erfahren

7Aggregationen: Minimum, Maximum und alles dazwischen

Summieren der Werte eines Arrays

Minimum und Maximum

Beispiel: Durchschnittliche Größe der US-Präsidenten

8Berechnungen mit Arrays: Broadcasting

Kurz vorgestellt: Broadcasting

Für das Broadcasting geltende Regeln

Broadcasting in der Praxis

9Vergleiche, Maskierungen und boolesche Logik

Beispiel: Regentage zählen

Vergleichsoperatoren als UFuncs

Boolesche Arrays verwenden

Boolesche Arrays als Maskierungen

Verwendung der Schlüsselwörter »and« bzw. »or« und der Operatoren & bzw. |

10Fancy Indexing

Fancy Indexing im Detail

Kombinierte Indizierung

Beispiel: Auswahl zufälliger Punkte

Werte per Fancy Indexing modifizieren

Beispiel: Daten gruppieren

11Arrays sortieren

Schnelle Sortierung in NumPy: np.sort und np.argsort

Nach Zeilen und Spalten sortieren

Teilsortierungen: Partitionierung

Beispiel: k nächste Nachbarn

12Strukturierte Daten: NumPys strukturierte Arrays

Strukturierte Arrays erzeugen

Erweiterte zusammengesetzte Typen

Record-Arrays: strukturierte Arrays mit Pfiff

Weiter mit Pandas

Teil III: Datenbearbeitung mit Pandas

13Kurz vorgestellt: Pandas-Objekte

Das Pandas-Series-Objekt

Das Pandas-DataFrame-Objekt

Das Pandas-Index-Objekt

14Daten indizieren und auswählen

Series-Daten auswählen

DataFrame-Daten auswählen

15Mit Pandas-Daten arbeiten

UFuncs: Indexerhaltung

UFuncs: Indexanpassung

UFuncs: Operationen mit DataFrame und Series

16Handhabung fehlender Daten

Kompromisse beim Umgang mit fehlenden Daten

Fehlende Daten in Pandas

Pandas nullfähige Datentypen

Mit Nullwerten arbeiten

17Hierarchische Indizierung

Mehrfach indizierte Series

Methoden zum Erzeugen eines MultiIndex

Indizierung und Slicing eines MultiIndex

Multi-Indizes umordnen

18Datenmengen kombinieren: concat und append

Verkettung von NumPy-Arrays

Einfache Verkettungen mit pd.concat

19Datenmengen kombinieren: merge und join

Relationale Algebra

Join-Kategorien

Angabe der zu verknüpfenden Spalten

Mengenarithmetik bei Joins

Konflikte bei Spaltennamen: das Schlüsselwort suffixes

Beispiel: Daten von US-Bundesstaaten

20Aggregation und Gruppierung

Planetendaten

Einfache Aggregationen in Pandas

GroupBy: Aufteilen, Anwenden und Kombinieren

21Pivot-Tabellen

Gründe für Pivot-Tabellen

Pivot-Tabellen von Hand erstellen

Die Syntax von Pivot-Tabellen

Beispiel: Geburtenraten

22Vektorisierte String-Operationen

Kurz vorgestellt: String-Operationen in Pandas

Liste der Pandas-String-Methoden

Beispiel: Rezeptdatenbank

23Zeitreihen verwenden

Kalenderdaten und Zeiten in Python

Zeitreihen in Pandas: Indizierung durch Zeitangaben

Datenstrukturen für Zeitreihen in Pandas

Gleichförmige Sequenzen: pd.date_range

Häufigkeiten und Abstände

Resampling, zeitliches Verschieben und geglättete Statistik

Beispiel: Visualisierung von Fahrradzählungen in Seattle

24Leistungsstarkes Pandas: eval und query

Der Zweck von query und eval: zusammengesetzte Ausdrücke

Effiziente Operationen mit pandas.eval

DataFrame.eval für spaltenweise Operationen

Die DataFrame.query-Methode

Performance: Wann eval und query verwendet werden sollten

Weitere Ressourcen

Teil IV: Visualisierung mit Matplotlib

25Allgemeine Tipps zu Matplotlib

Matplotlib importieren

Stil einstellen

show oder kein show? – Anzeige von Diagrammen

26Einfache Liniendiagramme

Anpassen des Diagramms: Linienfarben und -stile

Anpassen des Diagramms: Begrenzungen

Diagramme beschriften

Stolpersteine in Matplotlib

27Einfache Streudiagramme

Streudiagramme mit plt.plot erstellen

Streudiagramme mit plt.scatter erstellen

plot kontra scatter: eine Anmerkung zur Effizienz

Visualisierung von Messunsicherheiten

28Dichtediagramme und Konturdiagramme

Visualisierung einer dreidimensionalen Funktion

Histogramme, Binnings und Dichte

Zweidimensionale Histogramme und Binnings

29Anpassen der Legende

Legendenelemente festlegen

Legenden mit Punktgrößen

Mehrere Legenden

30Anpassen von Farbskalen

Farbskala anpassen

Beispiel: Handgeschriebene Ziffern

31Untergeordnete Diagramme

plt.axes: untergeordnete Diagramme von Hand erstellen

plt.subplot: untergeordnete Diagramme in einem Raster anordnen

plt.subplots: das gesamte Raster gleichzeitig ändern

plt.GridSpec: kompliziertere Anordnungen

32Text und Beschriftungen

Beispiel: Auswirkungen von Feiertagen auf die Geburtenzahlen in den USA

Transformationen und Textposition

Pfeile und Beschriftungen

33Achsenmarkierungen anpassen

Vorrangige und nachrangige Achsenmarkierungen

Markierungen oder Beschriftungen verbergen

Anzahl der Achsenmarkierungen verringern oder erhöhen

Formatierung der Achsenmarkierungen

Zusammenfassung der Formatter- und Locator-Klassen

34Matplotlib anpassen: Konfigurationen und Stylesheets

Diagramme von Hand anpassen

Voreinstellungen ändern: rcParams

35Dreidimensionale Diagramme in Matplotlib

Dreidimensionale Punkte und Linien

Dreidimensionale Konturdiagramme

Drahtgitter- und Oberflächendiagramme

Triangulation von Oberflächen

Beispiel: Visualisierung eines Möbiusbands

36Visualisierung mit Seaborn

Seaborn-Diagramme

Kategoriale Diagramme

Beispiel: Ergebnisse eines Marathonlaufs

Weiterführende Ressourcen

Weitere Grafikbibliotheken für Python

Teil V: Machine Learning

37Was ist Machine Learning?

Kategorien des Machine Learning

Qualitative Beispiele für Machine-Learning-Anwendungen

Zusammenfassung

38Kurz vorgestellt: Scikit-Learn

Datenrepräsentierung in Scikit-Learn

Die Estimator-API

Anwendung: Handgeschriebene Ziffern untersuchen

Zusammenfassung

39Hyperparameter und Modellvalidierung

Überlegungen zum Thema Modellvalidierung

Auswahl des besten Modells

Lernkurven

Validierung in der Praxis: Rastersuche

Zusammenfassung

40Feature Engineering

Kategoriale Features

Texte als Features

Bilder als Features

Abgeleitete Features

Vervollständigung fehlender Daten

Feature-Pipelines

41Ausführlich: Naive Bayes-Klassifikation

Bayes-Klassifikation

Gaußsche naive Bayes-Klassifikation

Multinomiale naive Bayes-Klassifikation

Einsatzgebiete für naive Bayes-Klassifikation

42Ausführlich: Lineare Regression

Einfache lineare Regression

Regression der Basisfunktion

Regularisierung

Beispiel: Vorhersage des Fahrradverkehrs

43Ausführlich: Support Vector Machines

Gründe für Support Vector Machines

Support Vector Machines: Maximierung des Randbereichs

Beispiel: Gesichtserkennung

Zusammenfassung

44Ausführlich: Entscheidungsbäume und Random Forests

Gründe für Random Forests: Entscheidungsbäume

Estimator-Ensembles: Random Forests

Random-Forest-Regression

Beispiel: Random Forest zur Klassifikation handgeschriebener Ziffern

Zusammenfassung

45Ausführlich: Hauptkomponentenanalyse

Hauptkomponentenanalyse: ein Überblick

Hauptkomponentenanalyse als Rauschfilter

Beispiel: Eigengesichter

Zusammenfassung

46Ausführlich: Manifold Learning

Manifold Learning: »HELLO«

Multidimensionale Skalierung

Nichtlineare Mannigfaltigkeiten: lokal lineare Einbettung

Überlegungen zum Thema Manifold-Methoden

Beispiel: Isomap und Gesichter

Beispiel: Visualisierung der Strukturen in Zifferndaten

47Ausführlich: k-Means-Clustering

Kurz vorgestellt: der k-Means-Algorithmus

Expectation-Maximization

Beispiele

48Ausführlich: Gaußsche Mixture-Modelle

Gründe für GMM: Schwächen von k-Means

EM-Verallgemeinerung: gaußsche Mixture-Modelle

Wahl des Kovarianztyps

GMM als Dichteschätzung

Beispiel: GMM zum Erzeugen neuer Daten verwenden

49Ausführlich: Kerndichteschätzung

Gründe für Kerndichteschätzung: Histogramme

Kerndichteschätzung in der Praxis

Auswahl der Bandbreite durch Kreuzvalidierung

Beispiel: Nicht ganz so naive Bayes-Klassifikation

50Anwendung: Eine Gesichtserkennungspipeline

HOG-Features

HOG in Aktion: eine einfache Gesichtserkennung

Vorbehalte und Verbesserungen

Weitere Machine-Learning-Ressourcen

Index

Einleitung

Was ist Data Science?

In diesem Buch geht es darum, Data Science mithilfe von Python zu betreiben, daher stellt sich unmittelbar die Frage: Was ist Data Science überhaupt? Das genau zu definieren, erweist sich als überraschend schwierig, insbesondere in Anbetracht der Tatsache, wie geläufig dieser Begriff inzwischen geworden ist. Von lautstarken Kritikern wird er mitunter als eine überflüssige Bezeichnung abgetan (denn letzten Endes kommt keine Wissenschaft ohne Daten aus) oder für ein leeres Schlagwort gehalten, das lediglich dazu dient, Lebensläufe aufzupolieren, um die Aufmerksamkeit übereifriger Personalverantwortlicher zu erlangen.

Meiner Ansicht nach übersehen diese Kritiker dabei einen wichtigen Punkt. Trotz des mit dem Begriff einhergehenden Hypes ist Data Science wohl die beste Beschreibung für fachübergreifende Fähigkeiten, die in vielen Anwendungsbereichen in Wirtschaft und Wissenschaft immer wichtiger werden. Entscheidend ist hier die Interdisziplinarität: Ich halte Drew Conways Venn-Diagramm, das er im September 2010 erstmals in seinem Blog veröffentlichte, für die beste Definition von Data Science (siehe Abbildung 1).

Zwar sind einige der Bezeichnungen für die Schnittmengen etwas überspitzt formuliert, aber dennoch erfasst dieses Diagramm das Wesentliche dessen, was gemeint ist, wenn man von »Data Science« spricht: Es handelt sich um ein grundlegend interdisziplinäres Thema. Data Science umfasst drei verschiedene und sich überschneidende Bereiche: die Statistik, um (immer größer werdende) Datenmengen modellieren und zusammenfassen zu können, die Informatik, um Algorithmen für die effiziente Speicherung, Verarbeitung und Visualisierung dieser Daten entwerfen zu können, und das erforderliche Fachwissen (das wir uns als das »klassisch« Erlernte eines Fachgebiets vorstellen können), um sowohl die angemessenen Fragen zu stellen als auch die Antworten im richtigen Kontext zu bewerten.

In diesem Sinne möchte ich Sie ermutigen, Data Science nicht als ein neu zu erlernendes Fachwissensgebiet zu begreifen, sondern als neue Fähigkeiten, die Sie im Rahmen Ihres vorhandenen Fachwissens anwenden können. Ob Sie über Wahlergebnisse berichten, Aktienrenditen vorhersagen, Mausklicks auf Onlinewerbung optimieren, Mikroorganismen auf Mikroskopbildern identifizieren, nach neuen Arten astronomischer Objekte suchen oder mit irgendwelchen anderen Daten arbeiten: Ziel dieses Buchs ist es, Ihnen die Fähigkeit zu vermitteln, neuartige Fragen über das von Ihnen gewählte Fachgebiet zu stellen und diese zu beantworten.

Abbildung 1: Das Venn-Diagramm zur Data Science von Drew Conway (Quelle: Drew Conway (https://oreil.ly/PkOOw), Abdruck mit freundlicher Genehmigung)

An wen richtet sich dieses Buch?

Sowohl in meinen Vorlesungen an der Universität Washington als auch auf verschiedenen technisch orientierten Konferenzen und Treffen wird mir am häufigsten diese Frage gestellt: »Wie kann man Python am besten erlernen?« Bei den Fragenden handelt es sich im Allgemeinen um technisch interessierte Studenten, Entwicklerinnen oder Forscher, die oftmals schon über umfangreiche Erfahrung mit dem Schreiben von Code und der Verwendung von rechnergestützten und numerischen Tools verfügen. Die meisten dieser Personen möchten Python erlernen, um die Programmiersprache als Tool für datenintensive und rechnergestützte wissenschaftliche Aufgaben zu nutzen. Für diese Zielgruppe ist eine Vielzahl von Lernvideos, Blogbeiträgen und Tutorials online verfügbar. Allerdings frustriert mich bereits seit geraumer Zeit, dass es auf obige Frage keine wirklich eindeutige und gute Antwort gibt – und das war der Anlass für dieses Buch.

Das Buch ist nicht als Einführung in Python oder die Programmierung im Allgemeinen gedacht. Ich setze voraus, dass die Leserinnen und Leser mit der Programmiersprache Python vertraut ist. Dazu gehören das Definieren von Funktionen, die Zuweisung von Variablen, das Aufrufen der Methoden von Objekten, die Steuerung des Programmablaufs und weitere grundlegende Aufgaben. Das Buch soll vielmehr Python-Usern dabei helfen, die zum Betreiben von Data Science verfügbaren Pakete zu nutzen – Bibliotheken wie die im folgenden Abschnitt genannten und ähnliche Tools –, um Daten effektiv zu speichern, zu handhaben und Einblick in diese Daten zu gewinnen.

Warum Python?

Python hat sich in den vergangenen Jahrzehnten zu einem erstklassigen Tool für wissenschaftliche Berechnungen entwickelt, insbesondere auch für die Analyse und Visualisierung großer Datensätze. Die ersten Anhänger der Programmiersprache Python dürfte das ein wenig überraschen: Beim eigentlichen Design der Sprache wurde weder der Datenanalyse noch wissenschaftlichen Berechnungen besondere Beachtung geschenkt. Dass sich Python für die Data Science als so nützlich erweist, ist vor allem dem großen und aktiven Ökosystem der Programmpakete von Drittherstellern zu verdanken: Da gibt es NumPy für die Handhabung gleichartiger Array-basierter Daten, Pandas für die Verarbeitung verschiedenartiger und gelabelter Daten, SciPy für gängige wissenschaftliche Berechnungen, Matplotlib für druckreife Visualisierungen, IPython für die interaktive Ausführung und zum Teilen von Code, Scikit-Learn für Machine Learning sowie viele weitere Tools, die auf den folgenden Seiten vorgestellt werden.

Falls Sie auf der Suche nach einer Einführung in die Programmiersprache Python sind, empfehle ich das dieses Buch ergänzende Projekt A Whirlwind Tour of Python (https://oreil.ly/jFtWj). Bei diesem kurzen Bericht handelt es sich um eine Tour durch die wesentlichen Features der Sprache Python, die sich an Data Scientists richtet, die bereits mit anderen Programmiersprachen vertraut sind.

Inhaltsübersicht

Alle nummerierten Teile in diesem Buch konzentrieren sich auf ein bestimmtes Paket oder Tool, das für die mit Python betriebene Data Science von grundlegender Bedeutung ist. Sie sind in eigenständige Kapitel unterteilt, die jeweils ein bestimmtes Konzept behandeln.

Teil I

, »

Mehr als normales Python: Jupyter

«, stellt IPython und Jupyter vor. Diese Pakete bieten eine Umgebung für Berechnungen, die von vielen Data Scientists genutzt wird, die Python einsetzen.

Teil II

, »

Einführung in NumPy

«, konzentriert sich auf die NumPy-Bibliothek, die das

ndarray

bereitstellt, das ein effizientes Speichern und die Handhabung dicht gepackter Daten-Arrays in Python ermöglicht.

Teil III

, »

Datenbearbeitung mit Pandas

«, stellt die Pandas-Bibliothek vor. Sie verfügt über das

DataFrame

-Objekt, das ein effizientes Speichern und die Handhabung gelabelter bzw. spaltenorientierter Daten in Python gestattet.

Teil IV

, »

Visualisierung mit Matplotlib

«, konzentriert sich auf Matplotlib, eine Bibliothek, die flexible und vielfältige Visualisierungen von Daten in Python ermöglicht.

Teil V

, »

Machine Learning

«, zeigt die Bibliothek Scikit-Learn. Sie stellt eine effiziente Implementierung der wichtigsten und gebräuchlichsten Machine-Learning-Algorithmen zur Verfügung.

Natürlich umfasst die PyData-Welt viel mehr als diese sechs Pakete – und sie wächst mit jedem Tag weiter. Ich werde mich im Folgenden daher bemühen, Hinweise auf andere interessante Projekte, Bestrebungen und Pakete zu geben, die die Grenzen des mit Python Machbaren erweitern. Dessen ungeachtet sind die Pakete, auf die ich mich hier konzentriere, derzeit für viele der mit Python möglichen Aufgaben der Data Science von grundlegender Bedeutung, und ich erwarte, dass sie wichtig bleiben, auch wenn das sie umgebende Ökosystem weiterhin wächst.

Installation der Software

Die Installation von Python und den für wissenschaftliche Berechnungen erforderlichen Bibliotheken ist unkompliziert. In diesem Abschnitt finden Sie einige Überlegungen, denen Sie bei der Einrichtung Ihres Computers Beachtung schenken sollten.

Es gibt zwar verschiedene Möglichkeiten, Python zu installieren, allerdings empfehle ich zum Betreiben von Data Science die Anaconda-Distribution, die unter Windows, Linux und macOS auf ähnliche Weise funktioniert. Es gibt zwei Varianten der Anaconda-Distribution:

Miniconda (

https://oreil.ly/dH7wJ

) besteht aus dem eigentlichen Python-Interpreter und einem Kommandozeilenprogramm namens

conda

, das als plattformübergreifender Paketmanager für Python-Pakete fungiert. Das Programm arbeitet in ähnlicher Weise wie die Tools

apt

oder

yum

, die Linux-Usern bekannt sein dürften.

Anaconda (

https://oreil.ly/ndxjm

) enthält sowohl Python als auch

conda

und darüber hinaus eine Reihe vorinstallierter Pakete, die für wissenschaftliche Berechnungen konzipiert sind. Aufgrund der Größe dieser Pakete müssen Sie davon ausgehen, dass die Installation mehrere Gigabyte Speicherplatz auf der Festplatte belegt.

Alle in Anaconda enthaltenen Pakete können auch nachträglich der Miniconda-Installation hinzugefügt werden. Daher empfehle ich, mit Miniconda anzufangen.

Laden Sie zunächst das Miniconda-Paket herunter und installieren Sie es. Vergewissern Sie sich, dass Sie eine Version auswählen, die Python 3 enthält. Installieren Sie dann die in diesem Buch verwendeten Pakete:

[~]$ conda install numpy pandas scikit-learn matplotlib seaborn jupyter

Wir werden im gesamten Buch noch weitere, spezialisiertere Tools einsetzen, die zum wissenschaftlich orientierten Ökosystem in Python gehören. Für gewöhnlich ist zur Installation lediglich eine Eingabe wie conda installpackagename nötig. Sollten Ihnen einmal Pakete begegnen, die über den Standard-conda-Kanal nicht erhältlich sind, sollten Sie auf jeden Fall auf conda-forge (https://oreil.ly/CCvwQ) nachsehen, einem vielfältigen, von der Community gepflegten Repository mit conda-Paketen. Weitere Informationen über conda, beispielsweise über das Erstellen und Verwenden von conda-Umgebungen (die ich nur nachdrücklich empfehlen kann), finden Sie in der Onlinedokumentation (https://oreil.ly/MkqPw).

In diesem Buch verwendete Konventionen

In diesem Buch gelten die folgenden typografischen Konventionen:

Kursiv

Kennzeichnet neue Begriffe, URLs, Dateinamen und Dateierweiterungen.

Nicht proportionale Schrift

Wird für Programmlistings und im Fließtext verwendet, um Programmbestandteile wie Variablen- oder Funktionsbezeichnungen, Datenbanken, Datentypen, Umgebungsvariablen, Anweisungen und Schlüsselwörter zu kennzeichnen.

Fette nicht proportionale Schrift

Kommandos oder sonstiger Text, der vom User buchstabengetreu eingegeben werden soll.

Kursive nicht proportionale Schrift

Text, der durch eigene Werte oder durch kontextabhängige Werte zu ersetzen ist.

Dieses Element steht für einen allgemeinen Hinweis.

Verwendung der Codebeispiele

Unter http://github.com/jakevdp/PythonDataScienceHandbook steht ergänzendes Material (Codebeispiele, Abbildungen usw.) zum Herunterladen zur Verfügung.

Dieses Buch soll Ihnen helfen, Ihre Arbeit zu erledigen. Den im Buch aufgeführten Code können Sie generell in Ihren eigenen Programmen und der Dokumentation verwenden. Sie brauchen uns nicht um Erlaubnis zu fragen, solange Sie nicht erhebliche Teile des Codes nutzen. Wenn Sie beispielsweise ein Programm schreiben, das einige der im Buch aufgeführten Codeschnipsel verwendet, benötigen Sie dafür keine Erlaubnis. Der Verkauf oder Vertrieb von Beispielen aus O’Reilly-Büchern bedarf hingegen einer Genehmigung. Das Beantworten von Fragen durch Verwendung von Zitaten oder Beispielcode aus diesem Buch muss nicht extra genehmigt werden. Die Verwendung erheblicher Teile des Beispielcodes in der Dokumentation Ihres eigenen Produkts erfordert jedoch eine Genehmigung.

Wir freuen uns über Quellennennungen, machen sie jedoch nicht zur Bedingung. Üblich ist die Nennung von Titel, Autor(en), Verlag, Erscheinungsjahr und ISBN, also beispielsweise: »Handbuch Data Science mit Python, 2. Auflage von Jake VanderPlas, O’Reilly 2024, ISBN 978-3-96009-225-4«.

Wenn Sie glauben, dass sich die Verwendung der Codebeispiele außerhalb der Fair-Use-Prinzipien oder der oben erwähnten Erlaubnis liegt, kontaktieren Sie uns bitte per E-Mail an [email protected].

TEIL I

Mehr als normales Python: Jupyter

Für Python stehen viele verschiedene Entwicklungsumgebungen zur Verfügung, und häufig werde ich gefragt, welche ich für meine eigenen Arbeiten verwende. Einige Menschen überrascht die Antwort: Meine bevorzugte Entwicklungsumgebung ist IPython (http://ipython.org) in Kombination mit einem Texteditor (entweder Emacs oder VSCode – das hängt von meiner Stimmung ab). Jupyter begann als die IPython-Shell, die 2001 von Fernando Perez in Form eines erweiterten Python-Interpreters ins Leben gerufen wurde und sich seither zu einem Projekt entwickelt hat, »Tools für den gesamten Lebenszyklus in der forschenden Informatik« – so Perez’ eigene Worte – bereitzustellen. Wenn man Python als Motor einer Aufgabe von Data Science betrachtet, können Sie sich Jupyter als die interaktive Steuerkonsole dazu vorstellen

Jupyter ist nicht nur eine nützliche interaktive Schnittstelle zu Python, sondern stellt darüber hinaus eine Reihe praktischer syntaktischer Erweiterungen der Sprache bereit. Die nützlichsten dieser Erweiterungen werden wir hier erörtern. Die bekannteste, vom Jupyter-Projekt bereitgestellte Schnittstelle ist wohl das Jupyter Notebook, eine browserbasierte Umgebung, die für die Entwicklung, die Zusammenarbeit, das Teilen und sogar die Veröffentlichung von Ergebnissen der Data Science gute Dienste leistet. Um ein Beispiel für die Nützlichkeit dieses Notebook-Formats zu geben: Betrachten Sie einfach nur die Seite, die Sie gerade lesen. Das vollständige Manuskript dieses Buchs wurde in Form einer Reihe von Jupyter Notebooks verfasst.

In diesem Teil des Buchs werden wir zunächst einige der Features von Jupyter betrachten, die sich in der Praxis der Data Science als nützlich erweisen. Der Schwerpunkt liegt hierbei auf der bereitgestellten Syntax, die mehr zu bieten hat als die Standardfeatures von Python. Anschließend werden wir uns etwas eingehender mit einigen der sehr nützlichen magischen Befehle befassen, die gängige Aufgaben bei der Erstellung und Verwendung des Data-Science-Codes beschleunigen können. Zum Abschluss erörtern wir dann einige der Features des Notebooks, die dem Verständnis der Daten und dem Teilen der Ergebnisse dienen können.

KAPITEL 1

Der Einstieg in IPython und Jupyter

Beim Schreiben von Code für Data Science verfolge ich normalerweise drei Arbeitsweisen: Ich benutze die IPython-Shell, um kurze Folgen von Befehlen auszuprobieren, das Jupyter Notebook für längere interaktive Analysen und um Inhalte mit anderen zu teilen sowie interaktive Entwicklungsumgebungen (IDEs) wie Emacs oder VSCode, um wiederverwendbare Python-Pakete zu erstellen. Dieses Kapitel konzentriert sich auf die ersten beiden Methoden: die IPython-Shell und das Jupyter Notebook. Der Einsatz einer IDE für die Softwareentwicklung ist ein wichtiges drittes Werkzeug im Repertoire der Data Scientists, auf das wir hier aber nicht direkt eingehen.

Die IPython-Shell starten

Wie die meisten Teile dieses Buchs sollte auch dieser nicht passiv gelesen werden. Ich empfehle Ihnen, während der Lektüre mit den vorgestellten Tools und der angegebenen Syntax herumzuexperimentieren. Die durch das Nachvollziehen der Beispiele erworbenen Fingerfertigkeiten werden sich als sehr viel nützlicher erweisen, als wenn Sie nur darüber lesen. Geben Sie auf der Kommandozeile ipython ein, um den Python-Interpreter zu starten. Sollten Sie eine Distribution wie Anaconda oder EPD (Enthought Python Distribution) installiert haben, können Sie möglicherweise alternativ einen systemspezifischen Programmstarter verwenden.

Nach dem Start des Interpreters sollte Ihnen eine Eingabeaufforderung wie die folgende angezeigt werden:

Python 3.9.2 (v3.9.2:1a79785e3e, Feb 19 2021, 09:06:10)

Type 'copyright', 'credits' or 'license' for more information

IPython 7.21.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

Nun können Sie fortfahren.

Das Jupyter Notebook starten

Das Jupyter Notebook ist eine browserbasierte grafische Schnittstelle für die IPython-Shell und besitzt eine große Vielfalt dynamischer Anzeigemöglichkeiten. Neben der Ausführung von Python-/IPython-Anweisungen gestattet das Notebook dem User das Einfügen von formatiertem Text, statischen und dynamischen Visualisierungen, mathematischen Formeln, JavaScript-Widgets und vielem mehr. Darüber hinaus können die Dokumente in einem Format gespeichert werden, das anderen Usern ermöglicht, sie auf ihren eigenen Systemen zu öffnen und den Code auszuführen.

Das Jupyter Notebook wird zwar in einem Fenster Ihres Webbrowsers angezeigt und bearbeitet, allerdings ist eine Verbindung zu einem laufenden Python-Prozess erforderlich, um Code auszuführen. Geben Sie in Ihrer System-Shell folgenden Befehl ein, um diesen Prozess (der als »Kernel« bezeichnet wird) zu starten:

$ jupyter lab

Dieser Befehl startet einen lokalen Webserver, auf den Ihr Browser zugreifen kann. Er gibt sofort einige Meldungen aus, die zeigen, was vor sich geht. Dieses Log sieht in etwa folgendermaßen aus:

$ jupyter lab

[ServerApp] Serving notebooks from local directory: /Users/jakevdp/ \

PythonDataScienceHandbook

[ServerApp] Jupyter Server 1.4.1 is running at:

[ServerApp] http://localhost:8888/lab?token=dd852649

[ServerApp] Use Control-C to stop this server and shut down all kernels

(twice to skip confirmation).

Nach der Eingabe des Befehls sollte sich automatisch Ihr Standardbrowser öffnen und die genannte lokale URL anzeigen. Die genaue Adresse ist von Ihrem System abhängig. Öffnet sich Ihr Browser nicht automatisch, können Sie von Hand ein Browserfenster öffnen und die Adresse (in diesem Beispiel http://localhost:8888/lab/) eingeben.

Hilfe und Dokumentation in IPython

Auch wenn Sie die anderen Abschnitte dieses Kapitels überspringen, sollten Sie doch wenigstens diesen lesen: Ich habe festgestellt, dass die hier erläuterten IPython-Tools den größten Einfluss auf meinen alltäglichen Arbeitsablauf haben.

Wenn ein technologisch interessierter Mensch darum gebeten wird, einem Freund, einem Familienmitglied oder einer Kollegin bei einem Computerproblem zu helfen, geht es meistens gar nicht darum, die Lösung zu kennen, sondern zu wissen, wie man schnell eine noch unbekannte Lösung findet. Mit Data Science verhält es sich ähnlich: Durchsuchbare Webressourcen wie Onlinedokumentationen, Mailinglisten und auf Stackoverflowbusiness.com gefundene Antworten enthalten jede Menge Informationen, auch (oder gerade?) wenn es sich um ein Thema handelt, nach dem Sie selbst schon einmal gesucht haben. Für einen leistungsfähigen Praktiker der Data Science geht es weniger darum, das in jeder erdenklichen Situation einzusetzende Tool oder den geeigneten Befehl auswendig zu lernen, sondern vielmehr darum, zu wissen, wie man die benötigten Informationen schnell und einfach findet – sei es nun mithilfe einer Suchmaschine oder auf anderem Weg.

Zwischen dem User und der erforderlichen Dokumentation sowie den Suchvorgängen, die ein effektives Arbeiten ermöglichen, klafft eine Lücke. Diese zu schließen, ist eine der nützlichsten Funktionen von IPython/Jupyter. Zwar spielen Suchvorgänge im Web bei der Beantwortung komplizierter Fragen nach wie vor eine Rolle, allerdings stellt IPython bereits eine bemerkenswerte Menge an Informationen bereit. Hier einige Beispiele für Fragen, bei deren Beantwortung IPython nach einigen wenigen Tastendrücken hilfreich sein kann:

Wie rufe ich eine bestimmte Funktion auf? Welche Argumente und Optionen besitzt sie?

Wie sieht der Quellcode eines bestimmten Python-Objekts aus?

Was ist in einem importierten Paket enthalten?

Welche Attribute oder Methoden besitzt ein Objekt?

Wir erörtern nun die Tools von IPython und Jupyter für den schnellen Zugriff auf diese Informationen, nämlich das Zeichen ? zum Durchsuchen der Dokumentation, die beiden Zeichen ?? zum Erkunden des Quellcodes und die Tabulatortaste (Tab-Taste), die eine automatische Vervollständigung ermöglicht.

Mit ? auf die Dokumentation zugreifen

Die Programmiersprache Python und das für die Data Science geeignete Ökosystem schenken den Nutzerinnen und Nutzern große Beachtung. Dazu gehört insbesondere der Zugang zur Dokumentation. Alle Python-Objekte enthalten einen Verweis auf einen String, den sogenannten Docstring, der wiederum in den meisten Fällen eine kompakte Übersicht über das Objekt und dessen Verwendung enthält. Python verfügt über eine integrierte help-Funktion, die auf diese Informationen zugreift und sie ausgibt. Um beispielsweise die Dokumentation der integrierten Funktion len anzuzeigen, können Sie Folgendes eingeben:

In [1]: help(len)

Help on built-in function len in module builtins:

len(obj, /)

Return the number of items in a container.

Je nachdem, welchen Interpreter Sie verwenden, wird der Text auf der Konsole oder in einem eigenen Fenster ausgegeben.

Die Suche nach der Hilfe für ein Objekt ist äußerst nützlich und sehr häufig notwendig. Daher verwendet IPython das Zeichen ? als Abkürzung für den Zugriff auf die Dokumentation und weitere wichtige Informationen:

In [2]: len?

Signature: len(obj, /)

Docstring: Return the number of items in a container.

Type: builtin_function_or_method

Diese Schreibweise funktioniert praktisch mit allem, auch mit Objektmethoden:

Und sogar mit Objekten selbst – dann wird die Dokumentation des Objekttyps angezeigt:

In [5]: L?

Type: list

String form: [1, 2, 3]

Length: 3

Docstring:

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list.

The argument must be an iterable if specified.

Wichtig zu wissen ist, dass das ebenfalls mit Funktionen und anderen von Ihnen selbst erzeugten Objekten funktioniert:

In [6]: def square(a):

....: """Return the square of a."""

....: return a ** 2

....:

Beachten Sie hier, dass wir zum Erstellen des Docstrings unserer Funktion einfach eine literale Zeichenkette in die erste Zeile eingegeben haben. Da Docstrings für gewöhnlich mehrzeilig sind, haben wir gemäß Konvention Pythons Schreibweise für mehrzeilige Strings mit dreifachem Anführungszeichen verwendet.

Nun verwenden wir das Zeichen ?, um diesen Docstring anzuzeigen:

In [7]: square?

Signature: square(a)

Docstring: Return the square of a.

File: <ipython-input-6>

Type: function

Dieser schnelle Zugriff auf die Dokumentation via Docstring ist einer der Gründe dafür, dass Sie sich angewöhnen sollten, den von Ihnen geschriebenen Code immer zu dokumentieren!

Mit ?? auf den Quellcode zugreifen

Da die Programmiersprache Python sehr leicht verständlich ist, können Sie für gewöhnlich tiefere Einblicke gewinnen, wenn Sie sich den Quellcode eines Objekts ansehen, das Sie interessiert. Mit einem doppelten Fragezeichen (??) stellen IPython und Jupyter eine Abkürzung für den Zugriff auf den Quellcode zur Verfügung:

In [8]: square??

Signature: square(a)

Source:

def square(a):

"""Return the square of a."""

return a ** 2

File: <ipython-input-6>

Type: function

Bei so einfachen Funktionen wie dieser können Sie mit dem doppelten Fragezeichen einen schnellen Blick darauf werfen, was unter der Haube vor sich geht.

Wenn Sie damit weiter herumexperimentieren, werden Sie feststellen, dass ein angehängtes ?? manchmal gar keinen Quellcode anzeigt. Das liegt im Allgemeinen daran, dass das fragliche Objekt nicht in Python implementiert ist, sondern in C oder einer anderen kompilierten Erweiterungssprache. In diesem Fall liefert ?? dieselbe Ausgabe wie ?. Das kommt insbesondere bei vielen in Python fest integrierten Objekten und Typen vor, wie beispielsweise bei der vorhin erwähnten Funktion len:

In [9]: len??

Signature: len(obj, /)

Docstring: Return the number of items in a container.

Type: builtin_function_or_method

Der Einsatz von ? und/oder ?? bietet eine schnelle und leistungsfähige Möglichkeit für das Auffinden von Informationen darüber, was in einer Python-Funktion oder einem Python-Modul eigentlich geschieht.

Module mit der Tab-Vervollständigung erkunden

Eine weitere nützliche Schnittstelle ist die Verwendung der Tabulatortaste zur automatischen Vervollständigung und zum Erkunden des Inhalts von Objekten, Modulen und Namensräumen. In den folgenden Beispielen wird durch <TAB> angezeigt, dass die Tabulatortaste gedrückt werden muss.

Tab-Vervollständigung des Inhalts von Objekten

Jedes Python-Objekt besitzt verschiedene Attribute und Methoden, die ihm zugeordnet sind. Neben dem bereits erläuterten help verfügt Python über eine integrierte dir-Funktion, die eine Liste dieser Attribute und Methoden ausgibt. Allerdings ist es in der Praxis viel einfacher, die Tab-Vervollständigung zu verwenden. Um eine Liste aller verfügbaren Attribute anzuzeigen, geben Sie einfach den Namen des Objekts ein, gefolgt von einem Punkt (.) und einem Druck auf die Tab-Taste:

In [10]: L.<TAB>

append() count insert reverse

clear extend pop sort

copy index remove

Um die Anzahl der Treffer in der Liste zu verringern, geben Sie einfach den ersten oder mehrere Buchstaben des Namens ein. Nach dem Drücken der Tab-Taste werden dann nur noch die übereinstimmenden Attribute und Methoden angezeigt:

In [10]: L.c<TAB>

clear() count()

copy()

In [10]: L.co<TAB>

copy() count()

Wenn der Treffer eindeutig ist, wird die Zeile durch ein weiteres Drücken der Tabulatortaste vervollständigt. Die folgende Eingabe wird beispielsweise sofort zu L.count vervollständigt:

In [10]: L.cou<TAB>

Python erzwingt zwar keine strenge Unterscheidung zwischen öffentlichen/externen und privaten/internen Attributen, allerdings gibt es die Konvention, Letztere durch einen vorangestellten Unterstrich zu kennzeichnen. Der Einfachheit halber werden die privaten und besonderen Methoden in der Liste standardmäßig weggelassen. Es ist jedoch möglich, sie durch ausdrückliche Eingabe des Unterstrichs anzuzeigen:

In [10]: L._<TAB>

__add__ __delattr__ __eq__

__class__ __delitem__ __format__()

__class_getitem__() __dir__() __ge__ >

__contains__ __doc__ __getattribute__

Wir zeigen hier nur kurz die ersten paar Zeilen der Ausgabe. Bei den meisten handelt es sich um Pythons spezielle Methoden, deren Namen mit einem doppelten Unterstrich beginnen (engl. double underscore, daher oft auch »dunder«-Methoden genannt).

Tab-Vervollständigung beim Importieren

Die Tab-Vervollständigung kann außerdem beim Importieren von Objekten aus Paketen helfen. Hier benutzen wir sie, um alle möglichen Importe aus dem Paket itertools zu finden, die mit der Zeichenkette co beginnen:

In [10]: from itertools import co<TAB>

combinations() compress()

combinations_with_replacement() count()

Auf ähnliche Weise können Sie die Tab-Vervollständigung einsetzen, um zu sehen, welche Importe auf Ihrem System verfügbar sind (das kann sich ändern, je nachdem, welche Skripte oder Module von Drittherstellern für Ihre Python-Sitzung sichtbar sind):

In [10]: import <TAB>

abc anyio

activate_this appdirs

aifc appnope >

antigravity argon2

In [10]: import h<TAB>

hashlib html

heapq http

hmac

Mehr als die Tab-Vervollständigung: Suche mit Wildcards

Die Tab-Vervollständigung ist nützlich, wenn Ihnen die ersten paar Buchstaben des Namens eines Objekts oder Attributs bekannt sind, das Sie suchen, hilft aber nicht weiter, wenn Sie nach übereinstimmenden Zeichen in der Mitte oder am Ende einer Bezeichnung suchen. Für diesen Anwendungsfall halten IPython und Jupyter mit dem Zeichen * eine Suche mithilfe von Wildcards bereit.

Wir können das Zeichen beispielsweise verwenden, um alle Objekte im Namensraum anzuzeigen, deren Namen auf Warning enden:

In [10]: *Warning?

BytesWarning RuntimeWarning

DeprecationWarning SyntaxWarning

FutureWarning UnicodeWarning

ImportWarning UserWarning

PendingDeprecationWarning Warning

ResourceWarning

Beachten Sie, dass das Zeichen * mit allen Strings übereinstimmt – auch mit einer leeren Zeichenkette.

Nehmen wir nun an, wir suchten nach einer String-Methode, die an irgendeiner Stelle in ihrem Namen das Wort find enthält. Auf diese Weise können wir sie finden:

In [11]: str.*find*?

str.find

str.rfind

Ich finde diese Art der flexiblen Suche mit Wildcards äußerst nützlich, um einen bestimmten Befehl zu finden, wenn ich ein neues Paket erkunde oder mich mit einem bereits bekannten erneut vertraut mache.

Tastaturkürzel in der IPython-Shell

Auch wenn Sie nur wenig Zeit mit einem Computer verbringen, werden Sie vermutlich bereits festgestellt haben, dass sich das eine oder andere Tastaturkürzel für Ihren Arbeitsablauf als nützlich erweist. Am bekanntesten sind vielleicht Strg-C und Strg-V (bzw. Cmd-C und Cmd-V) zum Kopieren und Einfügen in vielen ganz verschiedenen Programmen und Systemen. Erfahrene User gehen oft sogar noch einen Schritt weiter: Gängige Texteditoren wie Emacs, Vim und andere stellen einen immensen Umfang an verschiedenen Funktionen durch komplizierte Kombinationen von Tastendrücken zur Verfügung.

Ganz so weit geht die IPython-Shell nicht, dennoch bietet sie einige Tastaturkürzel zum schnellen Navigieren beim Eingeben von Befehlen. Einige der Tastaturkürzel funktionieren eventuell auch in browserbasierten Notebooks, allerdings geht es in diesem Abschnitt vornehmlich um die Tastaturkürzel in der IPython-Shell.

Sobald Sie sich daran gewöhnt haben, sind sie äußerst nützlich, um schnell bestimmte Befehle auszuführen, ohne die Hände von der Tastatur nehmen zu müssen. Sollten Sie Emacs-User sein oder Erfahrung mit Linux-Shells haben, wird Ihnen das Folgende bekannt vorkommen. Ich gruppiere die Befehle nach bestimmten Kategorien: Tastaturkürzel zum Navigieren, Tastaturkürzel bei der Texteingabe, Tastaturkürzel für den Befehlsverlauf und sonstige Tastaturkürzel.

Tastaturkürzel zum Navigieren

Dass die nach links und rechts weisenden Pfeiltasten dazu dienen, den Cursor in der Zeile rückwärts bzw. vorwärts zu bewegen, ist ziemlich offensichtlich, es gibt jedoch weitere Möglichkeiten, die es nicht erforderlich machen, Ihre Hände aus der gewohnten Schreibposition zu bewegen.

Tastaturkürzel

Beschreibung

Strg-A

Bewegt den Cursor an den Zeilenanfang.

Strg-E

Bewegt den Cursor an das Zeilenende.

Strg-B (oder Pfeiltaste nach links)

Bewegt den Cursor ein Zeichen rückwärts.

Strg-F (oder Pfeiltaste nach rechts)

Bewegt den Cursor ein Zeichen vorwärts.

Tastaturkürzel bei der Texteingabe

Jeder Nutzerin und jedem Nutzer ist die Verwendung der Rückschritttaste zum Löschen des zuvor eingegebenen Zeichens bekannt, allerdings sind oftmals einige Fingerverrenkungen erforderlich, um sie zu erreichen, und außerdem löscht sie beim Drücken jeweils nur ein einzelnes Zeichen. In IPython gibt es einige Tastaturkürzel zum Löschen bestimmter Teile der eingegebenen Textzeile. Sofort nützlich sind die Befehle zum Löschen der ganzen Textzeile. Sie sind Ihnen in Fleisch und Blut übergegangen, wenn Sie feststellen, dass Sie die Tastenkombinationen Strg-B und Strg-D verwenden, anstatt die Rückschritttaste zu benutzen, um das zuvor eingegebene Zeichen zu löschen!

Tastaturkürzel

Beschreibung

Rückschritttaste

Zeichen links vom Cursor löschen.

Strg-D

Zeichen rechts vom Cursor löschen.

Strg-K

Text von der Cursorposition bis zum Zeilenende ausschneiden.

Strg-U

Text vom Zeilenanfang bis zur Cursorposition ausschneiden.

Strg-Y

Zuvor ausgeschnittenen Text einfügen.

Strg-T

Die beiden zuletzt eingegebenen Zeichen vertauschen.

Tastaturkürzel für den Befehlsverlauf

Unter den hier aufgeführten von IPython bereitgestellten Tastaturkürzeln dürften diejenigen zur Navigation im Befehlsverlauf die größten Auswirkungen haben. Der Befehlsverlauf umfasst nicht nur die aktuelle IPython-Sitzung, Ihr gesamter Befehlsverlauf ist in einer SQLite-Datenbank im selben Verzeichnis gespeichert, in dem sich auch Ihr IPython-Profil befindet.

Die einfachste Zugriffsmöglichkeit auf Ihren Befehlsverlauf ist das Betätigen der Pfeiltasten nach oben und unten, mit denen Sie ihn schrittweise durchblättern können, es stehen aber noch andere Möglichkeiten zur Verfügung.

Tastaturkürzel

Beschreibung

Strg-P (oder Pfeiltaste nach oben)

Vorhergehenden Befehl im Verlauf auswählen.

Strg-N (oder Pfeiltaste nach unten)

Nachfolgenden Befehl im Verlauf auswählen.

Strg-R

Rückwärtssuche im Befehlsverlauf.

Die Rückwärtssuche kann besonders praktisch sein. Wie Sie wissen, haben wir im vorherigen Abschnitt eine Funktion namens square definiert. Durchsuchen Sie nun in einer neuen IPython-Shell den Befehlsverlauf nach dieser Definition. Wenn Sie im IPython-Terminal die Tastenkombination Strg-R drücken, wird Ihnen die folgende Eingabeaufforderung angezeigt:

In [1]:

(reverse-i-search)`':

Beginnen Sie nun damit, Zeichen einzugeben, zeigt IPython den zuletzt eingegebenen Befehl an (sofern vorhanden), der mit den eingegebenen Zeichen übereinstimmt:

In [1]:

(reverse-i-search)`squ': square??

Sie können jederzeit weitere Zeichen eingeben, um die Suche zu verfeinern, oder drücken Sie erneut Strg-R, um nach einem weiter zurückliegenden Befehl zu suchen, der zur Suchanfrage passt. Wenn Sie die Eingaben im letzten Abschnitt nachvollzogen haben, wird nach zweimaligem Betätigen von Strg-R Folgendes angezeigt:

In [1]:

(reverse-i-search)`squ': def square(a):

"""Return the square of a"""

return a ** 2

Sobald Sie den gesuchten Befehl gefunden haben, beenden Sie die Suche mit der Enter-Taste. Jetzt können Sie den gefundenen Befehl ausführen und die Sitzung fortsetzen:

In [1]: def square(a):

"""Return the square of a"""

return a ** 2

In [2]: square(2)

Out[2]: 4

Sie können auch die Tastenkombinationen Strg-P/Strg-N oder die Pfeiltasten nach oben und unten verwenden, um den Befehlsverlauf zu durchsuchen, allerdings werden dann bei der Suche lediglich die Zeichen am Anfang der Eingabezeile berücksichtigt. Wenn Sie also def eingeben und dann Strg-P drücken, wird der zuletzt eingegebene Befehl im Verlauf angezeigt (falls vorhanden), der mit den Zeichen def beginnt.

Sonstige Tastaturkürzel

Darüber hinaus gibt es einige weitere nützliche Tastaturkürzel, die sich keiner der bisherigen Kategorien zuordnen lassen.

Tastaturkürzel

Beschreibung

Strg-L

Terminalanzeige löschen.

Strg-C

Aktuellen Python-Befehl abbrechen.

Strg-D

Python-Sitzung beenden.

Insbesondere der Befehl Strg-C kann sich als nützlich erweisen, wenn Sie versehentlich einen sehr zeitaufwendigen Job gestartet haben.

Einige der hier vorgestellten Befehle mögen auf den ersten Blick vielleicht uninteressant erscheinen, Sie werden sie aber mit etwas Übung wie im Schlaf verwenden. Haben Sie sich diese Fingerfertigkeiten einmal angeeignet, werden Sie sich sogar wünschen, dass diese Befehle auch an anderer Stelle zur Verfügung stünden.

KAPITEL 2

Erweiterte interaktive Features

Ein großer Teil der Leistungsfähigkeit von IPython und Jupyter wird durch ihre zusätzlichen interaktiven Werkzeuge erreicht. In diesem Kapitel werden einige dieser Werkzeuge behandelt, darunter die sogenannten »magischen« Befehle. Dies sind Werkzeuge zur Untersuchung des Ein- und Ausgabeverlaufs und zur Interaktion mit der Shell.

Magische Befehle in IPython

Das vorherige Kapitel zeigt, wie IPython es Ihnen ermöglicht, Python effektiv und interaktiv zu verwenden und zu erkunden. Nun kommen wir zu einigen Erweiterungen, die IPython der normalen Python-Syntax hinzufügt. Diese werden in IPython als magische Befehle oder Funktionen bezeichnet, und ihnen wird ein %-Zeichen vorangestellt. Die magischen Befehle sind dazu gedacht, verschiedene gängige Aufgaben, die bei einer Standarddatenanalyse immer wieder vorkommen, kurz und bündig zu erledigen. Von den magischen Befehlen/Funktionen (den sogenannten Magics) gibt es zwei Varianten: Line-Magics, denen ein einzelnes % vorangestellt wird und die jeweils eine einzelne Zeile verarbeiten, sowie Cell-Magics, die durch ein vorangestelltes %% gekennzeichnet sind und mehrzeilige Eingaben verarbeiten. Wir werden einige kurze Beispiele betrachten und befassen uns dann später mit einer eingehenderen Erläuterung verschiedener nützlicher magischer Befehle.

Externen Code ausführen mit %run

Wenn Sie damit anfangen, umfangreicheren Code zu entwickeln, werden Sie vermutlich feststellen, dass Sie sowohl IPython für interaktive Erkundungen als auch einen Texteditor zum Speichern von Code einsetzen, den Sie wiederverwenden möchten. Oft ist es praktisch, den Code nicht in einem neuen Fenster, sondern innerhalb der laufenden IPython-Sitzung auszuführen. Zu diesem Zweck gibt es den magischen Befehl %run.

Nehmen wir beispielsweise an, Sie hätten eine Datei namens myscript.py angelegt, die folgenden Inhalt hat:

# file: myscript.py

def square(x):

"""square a number"""

return x ** 2

for N in range(1, 4):

print(f"{N} squared is {square(N)}")

Sie können dies wie folgt in Ihrer IPython-Sitzung ausführen:

In [1]: %run myscript.py

1 squared is 1

2 squared is 4

3 squared is 9

Beachten Sie hier außerdem, dass nach der Ausführung dieses Skripts die darin definierten Funktionen in Ihrer IPython-Sitzung verfügbar sind:

In [2]: square(5)

Out[2]: 25

Es stehen verschiedene Möglichkeiten zur Verfügung, genauer einzustellen, wie Ihr Code ausgeführt wird. Sie können sich durch die Eingabe von %run? wie gewohnt die Dokumentation im IPython-Interpreter anzeigen lassen.

Messung der Ausführungszeit von Code mit %timeit

Ein weiteres Beispiel einer nützlichen magischen Funktion ist %timeit, die automatisch die Ausführungszeit einer einzeiligen Python-Anweisung ermittelt, die dem Befehl übergeben wird. Wir könnten beispielsweise die Performance einer Listenabstraktion wie folgt ermitteln:

Die %timeit-Funktion hat den Vorteil, dass sie bei kurzen Befehlen automatisch mehrere Durchläufe ausführt, um aussagekräftigere Ergebnisse zu erhalten. Bei mehrzeiligen Anweisungen macht das Hinzufügen eines zweiten %-Zeichens den Befehl zu einem Cell-Magic, das mehrzeilige Eingaben verarbeiten kann. Dies ist beispielsweise der entsprechende Code mit einer for-Schleife:

Wir können sofort feststellen, dass die Listenabstraktion in diesem Fall rund 10% schneller ist als die entsprechende for-Schleife. Wir werden uns mit %timeit und anderen Ansätzen für das Timing und Profiling von Code im Abschnitt »Profiling und Timing von Code« auf Seite 45 noch eingehender befassen.

Hilfe für die magischen Funktionen anzeigen mit ?, %magic und %lsmagic

Wie normale Python-Funktion besitzen auch IPythons magische Funktionen Docstrings, und auf diese nützliche Dokumentation kann man wie gewohnt zugreifen. Um also beispielsweise die Dokumentation des magischen Befehls %timeit zu lesen, geben Sie einfach Folgendes ein:

In [5]: %timeit?

Auf die Dokumentation anderer Funktionen wird auf ähnliche Weise zugegriffen. Zur Anzeige einer allgemeinen Beschreibung der verfügbaren magischen Funktionen inklusive einiger Beispiele geben Sie nachstehenden Befehl ein:

In [6]: %magic

Und so zeigen Sie schnell und einfach eine Liste aller zur Verfügung stehenden magischen Funktionen an:

In [7]: %lsmagic

Abschließend möchte ich noch erwähnen, dass es ganz einfach möglich ist, eigene magische Funktionen zu definieren. Wir werden darauf an dieser Stelle nicht weiter eingehen, aber wenn Sie daran interessiert sind, werfen Sie einen Blick auf die Hinweise im Abschnitt »Weitere IPython-Ressourcen« auf Seite 50.

Verlauf der Ein- und Ausgabe

Sie wissen bereits, dass die IPython-Shell es ermöglicht, mit den Pfeiltasten nach oben und unten (oder mit den entsprechenden Tastaturkürzeln Strg-P/Strg-N auf frühere Befehle zuzugreifen. Sowohl in der Shell als auch in Notebooks bietet IPython darüber hinaus verschiedene Möglichkeiten, die Ausgabe vorhergehender Befehle oder reine Textversionen der Befehle selbst abzurufen. Das sehen wir uns nun genauer an.

IPythons In- und Out-Objekte

Die von IPython verwendeten Ausgaben der Form In [1]:/Out[1]: dürften Ihnen inzwischen hinlänglich vertraut sein. Dabei handelt es sich jedoch keinesfalls nur um hübsche Verzierungen, vielmehr geben sie einen Hinweis darauf, wie Sie auf vorhergehende Ein- und Ausgaben Ihrer aktuellen Sitzung zugreifen können. Nehmen wir an, Sie starten eine Sitzung, die folgendermaßen aussieht:

In [1]: import math

In [2]: math.sin(2)

Out[2]: 0.9092974268256817

In [3]: math.cos(2)

Out[3]: -0.4161468365471424

Wir haben das integrierte math-Paket importiert und dann den Sinus und den Kosinus von 2 berechnet. Diese Ein- und Ausgaben werden in der Shell mit In/Out-Labels angezeigt. Das ist jedoch noch nicht alles – tatsächlich erzeugt IPython verschiedene Python-Variablen namens In und Out, die automatisch aktualisiert werden und so den Verlauf widerspiegeln:

In [4]: In

Out[4]: ['', 'import math', 'math.sin(2)', 'math.cos(2)', 'In']

In [5]: Out

Out[5]:

{2: 0.9092974268256817,

3: -0.4161468365471424,

4: ['', 'import math', 'math.sin(2)', 'math.cos(2)', 'In', 'Out']}

Das In-Objekt ist eine Liste, die über die Reihenfolge der Befehle Buch führt (das erste Element der Liste ist ein Platzhalter, sodass In[1] auf den ersten Befehl verweist):

In [6]: print(In[1])

import math

Das Out-Objekt hingegen ist keine Liste, sondern ein Dictionary, in dem die Eingabenummern den jeweiligen Ausgaben (falls vorhanden) zugeordnet sind:

In [7]: print(Out[2])

.9092974268256817

Beachten Sie hier, dass nicht alle Operationen eine Ausgabe erzeugen. Beispielsweise haben die import- und print-Anweisungen keine Auswirkung auf die Ausgabe. Letzteres überrascht vielleicht etwas, ergibt jedoch Sinn, wenn man bedenkt, dass print eine Funktion ist, die None zurückliefert. Kurz und bündig: Alle Befehle, die None zurückgeben, werden nicht zum Out-Dictionary hinzugefügt.

Das kann sich als nützlich erweisen, wenn Sie die letzten Ergebnisse verwenden möchten. Berechnen Sie beispielsweise die Summe von sin(2) ** 2 und cos(2) ** 2 unter Zuhilfenahme der zuvor errechneten Ergebnisse:

In [8]: Out[2] ** 2 + Out[3] ** 2

Out[8]: 1.0

Das Ergebnis lautet 1.0, wie es gemäß der wohlbekannten trigonometrischen Gleichung auch zu erwarten ist. In diesem Fall wäre es eigentlich gar nicht notwendig, die vorhergehenden Ergebnisse zu verwenden, allerdings kann es ungemein praktisch sein, wenn Sie eine sehr zeitaufwendige Berechnung ausführen und vergessen, das Ergebnis einer Variablen zuzuweisen!

Der Unterstrich als Abkürzung und vorhergehende Ausgaben

Die normale Python-Shell besitzt nur eine einfache Abkürzung für den Zugriff auf vorherige Ausgaben. Die Variable _ enthält das Ergebnis der jeweils letzten Ausgabe. In IPython funktioniert das ebenfalls:

In [9]: print(_)

.0

Allerdings geht IPython noch einen Schritt weiter – Sie können außerdem einen doppelten Unterstrich verwenden, um auf die vorletzte Ausgabe zuzugreifen, oder einen dreifachen, um auf die drittletzte Ausgabe zuzugreifen (wobei alle Befehle ohne Ausgabe übersprungen werden):

In [10]: print(__)

-0.4161468365471424

In [11]: print(___)

.9092974268256817

Hier ist in IPython jedoch Schluss: Mehr als drei Unterstriche sind etwas schwierig abzuzählen, und es ist einfacher, die Nummer der Ausgabe zu verwenden.

Eine weitere Abkürzung soll an dieser Stelle noch Erwähnung finden: _X (ein einfacher Unterstrich, gefolgt von der Ausgabenummer) ist die Abkürzung für Out[X]:

In [12]: Out[2]

Out[12]: 0.9092974268256817

In [13]: _2

Out[13]: 0.9092974268256817

Ausgaben unterdrücken

Manchmal ist es erwünscht, die Ausgaben einer Anweisung zu unterdrücken (am häufigsten kommt das vielleicht bei den Befehlen zum Erstellen von Diagrammen vor, mit denen wir uns in Teil IV befassen werden). Oder der auszuführende Befehl liefert ein Ergebnis, das Sie lieber nicht im Verlauf der Ausgabe speichern möchten, möglicherweise damit der dadurch belegte Speicherplatz wieder freigegeben wird, wenn es keine weiteren Referenzen mehr darauf gibt. Die einfachste Methode zum Unterdrücken der Ausgabe ist das Anhängen eines Semikolons an das Zeilenende:

In [14]: math.sin(2) + math.cos(2);

Beachten Sie hier, dass das Ergebnis zwar berechnet, aber weder auf dem Bildschirm angezeigt noch im Out-Dictionary gespeichert wird:

In [15]: 14 in Out

Out[15]: False

Weitere ähnliche magische Befehle

Mit dem magischen Befehl %history kann man auf mehrere vorhergehende Eingaben gleichzeitig zugreifen. So können Sie die ersten vier Eingaben anzeigen:

In [16]: %history -n 1-3

1: import math

2: math.sin(2)

3: math.cos(2)

Sie können wie gewohnt %history? eingeben, um weitere Informationen und eine Beschreibung der möglichen Optionen anzuzeigen. (Zusätzliche Details zur Funktionsweise von ? finden Sie in Kapitel 1.) Weitere nützliche magische Befehle sind %rerun (erneute Ausführung eines Teils des Befehlsverlaufs) und %save (zum Speichern eines Teils des Befehlsverlaufs in einer Datei).

IPython und Shell-Befehle

Wenn man einen normalen Python-Interpreter interaktiv verwendet, muss man sich damit herumärgern, dass man gezwungen ist, zwischen mehreren Fenstern hin und her zu schalten, um auf Python-Tools und Kommandozeilenprogramme des Systems zuzugreifen. IPython schließt diese Lücke und stellt eine Syntax zum Ausführen von Shell-Befehlen direkt im IPython-Terminal bereit. Möglich macht das ein Ausrufezeichen: Jeglicher nach einem ! stehender Text in einer Zeile wird nicht vom Python-Kernel, sondern von der Kommandozeile des Systems ausgeführt.

Im Folgenden wird vorausgesetzt, dass Sie ein unixoides System wie Linux oder macOS verwenden. Einige der Beispiele würden unter Windows fehlschlagen, das standardmäßig eine andere Art von Shell verwendet. Wenn Sie allerdings das Windows Subsystem for Linux (https://oreil.ly/H5MEE) verwenden, sollten die Beispiele korrekt ausgeführt werden. Sind Ihnen Shell-Befehle nicht geläufig, empfiehlt sich die Lektüre des Unix Shell-Tutorials (https://oreil.ly/RrD2Y), das von der ausgezeichneten Software Carpentry Foundation zusammengestellt wurde.

Kurz vorgestellt: die Shell

Eine vollständige Einführung in die Arbeit mit Shell, Terminal oder Kommandozeile geht weit über den Rahmen dieses Kapitels hinaus. An dieser Stelle folgt lediglich eine Kurzeinführung für diejenigen, die über gar keine Kenntnisse auf diesem Gebiet verfügen. Die Shell bietet eine Möglichkeit, per Texteingabe mit dem Computer zu interagieren. Seit Mitte der 1980er-Jahre, als Apple und Microsoft die ersten Versionen der heute allgegenwärtigen grafischen Betriebssysteme vorstellten, interagieren die meisten User mit ihrem Betriebssystem durch die vertraute Auswahl von Menüpunkten und durch Verschieben von Objekten mit der Maus. Nun gab es jedoch schon viel früher, lange bevor die grafischen Benutzeroberflächen entwickelt wurden, Betriebssysteme, die vornehmlich durch Texteingaben gesteuert wurden: Der User gibt auf der Kommandozeile einen Befehl ein, und der Computer führt aus, was der User ihm befohlen hat. Diese ersten Kommandozeilensysteme waren die Vorgänger der Shells und Terminals, die viele Data Scientists auch heute noch verwenden.

Wenn man mit der Shell nicht vertraut ist, mag man fragen, warum man sich diese Mühe machen sollte, wenn man doch mit ein paar Mausklicks auf Symbole und Menüs schon so viel erreichen kann. Ein Shell-User könnte mit einer Gegenfrage antworten: Warum irgendwelchen Symbolen nachjagen und Menüpunkte anklicken, wenn man seine Ziele durch Texteingaben viel einfacher erreichen kann? Zunächst hört sich das nach einer dieser typischen Pattsituationen zweier Lager mit unterschiedlichen Präferenzen an. Wenn jedoch mehr als nur grundlegende Arbeiten zu erledigen sind, wird schnell deutlich, dass die Shell bei anspruchsvolleren Aufgaben viel mehr Steuerungsmöglichkeiten bietet, wenngleich die Lernkurve zugegebenermaßen einschüchtern kann.

Nachstehend finden Sie als Beispiel eine Linux/macOS-Shell-Sitzung, in der ein User Dateien und Verzeichnisse auf dem System erkundet, anlegt und modifiziert (osx:~ $ ist die Eingabeaufforderung, und alles hinter dem $ ist der eingegebene Befehl; die Texte, denen ein # vorausgeht, sind lediglich Beschreibungen und müssen nicht eingetippt werden):

Wie Sie sehen, handelt es sich hier lediglich um eine kompakte Art und Weise, gängige Operationen (Navigieren in einer Verzeichnisstruktur, Anlegen eines Verzeichnisses, Datei verschieben usw.) durch die Eingabe von Befehlen auszuführen, statt Symbole und Menüs anzuklicken. Beachten Sie, dass sich die gebräuchlichsten Dateioperationen mit einigen wenigen Befehlen (pwd, ls, cd, mkdir und cp) erledigen lassen. Die wahre Leistungsfähigkeit der Shell zeigt sich vor allem aber dann, wenn man anspruchsvollere als diese grundlegenden Aufgaben erledigen möchte.

Shell-Befehle in IPython

Sie können sämtliche Standardbefehle der Kommandozeile direkt in IPython verwenden, indem Sie ihnen ein !-Zeichen voranstellen. So können die Befehle ls, pwd und echo beispielsweise folgendermaßen ausgeführt werden:

In [1]: !ls

myproject.txt

In [2]: !pwd

/home/jake/projects/myproject

In [3]: !echo "printing from the shell"

printing from the shell

Werte mit der Shell austauschen

Diese Ergebnisse werden nicht als Liste zurückgegeben, sondern als ein in IPython definierter spezieller Rückgabetyp für Shells:

In [8]: type(directory)

IPython.utils.text.SList

Dieser Typ sieht zwar wie eine Python-Liste aus und verhält sich auch sehr ähnlich, verfügt aber über zusätzliche Funktionalität, wie z.B. über die grep- und fields-Methoden sowie die Eigenschaften s, n und p, die es Ihnen erlauben, die Ergebnisse auf komfortable Art und Weise zu durchsuchen, zu filtern und anzuzeigen. Weitere Informationen dazu finden Sie in IPythons integrierter Hilfefunktion.

Die Kommunikation in der anderen Richtung, also die Übergabe von Python an die Shell, wird durch die Verwendung der Syntax {varname} ermöglicht:

Der Variablenname wird von den geschweiften Klammern eingeschlossen und wird im Shell-Befehl durch den Inhalt der Variablen ersetzt.

Magische Befehle für die Shell

Wenn Sie ein Weilchen mit IPythons Shell-Befehlen herumexperimentiert haben, ist Ihnen vielleicht aufgefallen, dass es nicht möglich ist, mit !cd im Dateisystem zu navigieren:

In [11]: !pwd

/home/jake/projects/myproject

In [12]: !cd ..

In [13]: !pwd

/home/jake/projects/myproject

Das liegt daran, dass die Shell-Befehle in einem Notebook in einer temporären Subshell ausgeführt werden, die den Zustand von Befehl zu Befehl nicht beibehält. Wenn Sie das Arbeitsverzeichnis dauerhaft ändern möchten, steht Ihnen dafür der magische Befehl %cd zur Verfügung:

In [14]: %cd ..

/home/jake/projects

Tatsächlich können Sie den Befehl standardmäßig sogar ohne das %-Zeichen aufrufen:

In [15]: cd myproject

/home/jake/projects/myproject

Man spricht hier von einer automagischen Funktion, deren Verhalten mit der magischen Funktion %automagic geändert werden kann.

Neben %cd gibt es für die Shell noch die magischen Funktionen %cat, %cp, %env, %ls, %man, %mkdir, %more, %mv, %pwd, %rm und %rmdir, die alle auch ohne das %-Zeichen verwendbar sind, sofern automagic eingeschaltet ist. Auf diese Weise können Sie die Kommandozeile in IPython fast wie eine normale Shell verwenden:

In [16]: mkdir tmp

In [17]: ls

myproject.txt tmp/

In [18]: cp myproject.txt tmp/

In [19]: ls tmp

myproject.txt

In [20]: rm -r tmp

Dieser Zugriff auf die Shell im selben Terminalfenster, in dem Ihre Python-Sitzung läuft, bedeutet für Sie beim Schreiben von Python-Code, dass Sie sehr viel weniger vom Interpreter zur Shell und wieder zurück wechseln müssen.

KAPITEL 3

Debugging und Profiling

Zusätzlich zu den fortgeschrittenen interaktiven Werkzeugen, die im vorherigen Kapitel besprochen wurden, bietet Jupyter eine Reihe von Möglichkeiten, den ausgeführten Code zu untersuchen und zu verstehen, beispielsweise durch das Auffinden von Fehlern in der Logik oder einer unerwartet langsamen Ausführung. Dieses Kapitel stellt einige dieser Werkzeuge vor.

Fehler und Debugging

Bei der Entwicklung von Code und der Datenanalyse spielen auch Versuch und Irrtum immer eine gewisse Rolle. IPython bringt einige Tools mit, um diesen Vorgang zu optimieren. In diesem Abschnitt werden wir uns kurz mit einigen Optionen zur Konfiguration der Fehlerberichterstattung (Exceptions) in IPython befassen. Anschließend erkunden wir die Tools für das Debuggen von Fehlern im Code.

Exceptions handhaben: %xmode

Wenn ein Python-Skript fehlschlägt, wird in den meisten Fällen eine Exception ausgelöst. Trifft der Interpreter auf eine solche Exception, finden sich Informationen über die Fehlerursache im sogenannten Traceback, auf das Sie von Python aus zugreifen können. Mit der magischen Funktion %xmode erhalten Sie von IPython die Möglichkeit, den Umfang der Informationen festzulegen, die ausgegeben werden, wenn eine Exception ausgelöst wird. Betrachten Sie den folgenden Code:

Der Aufruf von func2 verursacht einen Fehler, und im Traceback können wir genau sehen, was passiert ist. Standardmäßig enthält das Traceback einige Zeilen, die den Kontext der einzelnen Schritte zeigen, die zu dem Fehler geführt haben. Mit der magischen Funktion %xmode (kurz für exception mode) können wir ändern, welche Informationen ausgegeben werden.

%xmode benötigt ein einzelnes Argument, den Modus, für den es drei mögliche Werte gibt: Plain, Context und Verbose. Voreingestellt ist der Modus Context, der zu der obigen Ausgabe führt. Der Modus Plain sorgt für eine kompaktere Ausgabe und liefert weniger Informationen:

In [3]: %xmode Plain

Out[3]: Exception reporting mode: Plain

In [4]: func2(1)

Traceback (most recent call last):

File "<ipython-input-4-b2e110f6fc8f>", line 1, in <module>

func2(1)

File "<ipython-input-1-d849e34d61fb>", line 7, in func2

return func1(a, b)

File "<ipython-input-1-d849e34d61fb>", line 2, in func1

return a / b

ZeroDivisionError: division by zero

Im Modus Verbose werden einige zusätzliche Informationen ausgegeben, unter anderem die Argumente aller aufgerufenen Funktionen:

Diese zusätzlichen Informationen können Ihnen dabei helfen, einzugrenzen, warum eine Exception ausgelöst wird. Warum also nicht immer den Verbose-Modus nutzen? Wenn der Code komplizierter ist, kann diese Art des Tracebacks extrem umfangreich werden. Je nach Kontext lässt es sich manchmal besser mit der Knappheit des Plain- oder des Context-Modus arbeiten.

Debugging: Wenn das Lesen von Tracebacks nicht ausreicht

Das Standardtool für interaktives Debuggen ist pdb, der Python-Debugger. Mit diesem Debugger kann der User den Code Zeile für Zeile durchlaufen, um zu prüfen, was einen schwer zu findenden Fehler verursachen könnte. Die erweiterte IPython-Version heißt ipdb, das ist der IPython-Debugger.

Es gibt viele verschiedene Möglichkeiten, diese beiden Debugger zu starten und einzusetzen, die wir an dieser Stelle jedoch nicht vollständig abhandeln werden. Nutzen Sie die Onlinedokumentationen dieser beiden Hilfsprogramme, wenn Sie mehr erfahren möchten.

In IPython ist der magische Befehl %debug wohl die komfortabelste Debugging-Schnittstelle. Wenn Sie ihn aufrufen, nachdem eine Exception ausgelöst wurde, wird automatisch eine interaktive Kommandozeile geöffnet, und zwar an der Stelle, an der die Exception aufgetreten ist. Mit der ipdb-Kommandozeile können Sie den aktuellen Zustand des Stacks untersuchen, die Werte der verfügbaren Variablen anzeigen und sogar Python-Befehle ausführen!

Sehen wir uns also die letzte Exception einmal etwas genauer an. Wir führen einige grundlegende Aufgaben aus, nämlich die Ausgabe der Werte von a und b, und beenden die Debugging-Sitzung anschließend durch Eingabe von quit.

In [7]: %debug <ipython-input-1-d849e34d61fb>(2)func1()

1 def func1(a, b):

----> 2 return a / b

3

ipdb> print(a)

1

ipdb> print(b)

0

ipdb> quit

Der interaktive Debugger kann jedoch viel mehr als das – wir können sogar im Stack hinauf- und herabsteigen und die Werte der dort verfügbaren Variablen untersuchen:

Auf diese Weise können Sie nicht nur schnell herausfinden, was den Fehler verursacht hat, sondern auch, welche Funktionsaufrufe zu dem Fehler führten.

Wenn der Debugger automatisch starten soll, sobald eine Exception ausgelöst wird, nutzen Sie die magische Funktion %pdb, um dieses Verhalten zu aktivieren:

In [9]: %xmode Plain

%pdb on

func2(1)

Exception reporting mode: Plain

Automatic pdb calling has been turned ON

ZeroDivisionError: division by zero <ipython-input-1-d849e34d61fb>(2)func1()

1 def func1(a, b):

----> 2 return a / b

3

ipdb> print(b)

0

ipdb> quit

Und wenn Sie ein Skript von Anfang an im interaktiven Modus ausführen möchten, starten Sie es mit dem Befehl %run -d, Sie können dann mit dem Befehl next die Codezeilen schrittweise interaktiv durchlaufen.

Es sind deutlich mehr Befehle für den interaktiven Debugger verfügbar, als ich hier gezeigt habe. Tabelle 3-1 enthält eine kurze Beschreibung einiger der gebräuchlicheren Befehle.

Tabelle 3-1: Eine (unvollständige) Liste der Debugging-Befehle

Befehl

Beschreibung

l(ist)

Anzeige der aktuellen Position in der Datei.

h(elp)

Liste der Befehle oder Hilfe für einen bestimmten Befehl anzeigen.

q(uit)

Debugger und Programm beenden.

c(ontinue)

Den Debugger beenden und das Programm weiter ausführen.

n(ext)

Mit dem nächsten Schritt des Programms fortfahren.

<enter>

Den vorherigen Befehl wiederholen.

p(rint)

Variablen ausgeben.

s(tep)

In eine Subroutine springen.

r(eturn)

Aus einer Subroutine zurückkehren.

Verwenden Sie den help-Befehl im Debugger, um weitere Informationen aufzurufen, oder werfen Sie einen Blick in die Onlinedokumentation (https://oreil.ly/TVSAT) zu ipdb.

Profiling und Timing von Code

Bei der Entwicklung des Codes und der Erstellung von Datenverarbeitungspipelines muss man sich häufig zwischen verschiedenen Implementierungen entscheiden. In der Frühphase der Entwicklung eines Algorithmus kann es jedoch kontraproduktiv sein, sich darüber schon Gedanken zu machen. Oder wie Donald Knuth bekanntermaßen geistreich anmerkte: »Wir sollten es in vielleicht 97% aller Fälle bleiben lassen, uns mit winzigen Verbesserungen zu befassen: Verfrühte Optimierung ist die Wurzel allen Übels.«

Sobald der Code jedoch funktioniert, kann es durchaus sinnvoll sein, die Effizienz zu überprüfen. Manchmal erweist es sich als nützlich, die Ausführungszeit eines bestimmten Befehls oder einer Befehlsfolge zu messen. In anderen Fällen ist es hilfreich, mehrzeilige Codeabschnitte zu untersuchen und herauszufinden, an welcher Stelle es in einer komplizierten Abfolge von Operationen zu einem Engpass kommt. IPython bietet eine Vielzahl von Funktionen für diese Art des Timings und Profilings von Code. Im Folgenden betrachten wir die nachstehenden magischen Befehle in IPython:

%time

Die Ausführungszeit einer einzelnen Anweisung messen.

%timeit

Die Ausführungszeit einer einzelnen Anweisung mehrfach messen, um aussagekräftigere Ergebnisse zu erhalten.

%prun

Code mit dem Profiler ausführen.

%lprun

Code mit dem Profiler zeilenweise ausführen.

%memit

Den Speicherbedarf einer einzelnen Anweisung messen.

%mprun

Code mit dem Memory-Profiler zeilenweise ausführen.

Die letzten vier dieser Befehle sind nicht Bestandteil von IPython – Sie müssen die Erweiterungen line_profiler und memory_profiler installieren, die wir in den nächsten Abschnitten eingehender betrachten.

Timing von Codeschnipseln: %timeit und %time

Im Abschnitt »Magische Befehle in IPython« auf Seite 31 haben Sie das Line-Magic %timeit und das Cell-Magic %%timeit bereits kennengelernt. Mit beiden kann die für die wiederholte Ausführung einer Anweisung erforderliche Zeit gemessen werden:

In [1]: %timeit sum(range(100))