de
                    array(1) {
  ["de"]=>
  array(13) {
    ["code"]=>
    string(2) "de"
    ["id"]=>
    string(1) "3"
    ["native_name"]=>
    string(7) "Deutsch"
    ["major"]=>
    string(1) "1"
    ["active"]=>
    string(1) "1"
    ["default_locale"]=>
    string(5) "de_DE"
    ["encode_url"]=>
    string(1) "0"
    ["tag"]=>
    string(2) "de"
    ["missing"]=>
    int(0)
    ["translated_name"]=>
    string(7) "Deutsch"
    ["url"]=>
    string(79) "https://www.statworx.com/content-hub/blog/data-science-in-python-pandas-teil-3/"
    ["country_flag_url"]=>
    string(87) "https://www.statworx.com/wp-content/plugins/sitepress-multilingual-cms/res/flags/de.png"
    ["language_code"]=>
    string(2) "de"
  }
}
                    
Kontakt
Content Hub
Blog Post

Data Science in Python – Pandas – Teil 3

  • Expert:innen Moritz Gnisia
  • Datum 22. Mai 2018
  • Thema CodingData SciencePython
  • Format Blog
  • Kategorie Technology
Data Science in Python – Pandas – Teil 3

Nachdem mein Kollege Marvin in seinem Artikel die Bibliothek NumPy vorgestellt hat, wird sich dieser STATWORX Blog Beitrag rund um die Bibliothek Pandas drehen. Pandas fußt zu einem großen Teil auf NumPy, bietet allerdings gerade für einen Einsteiger in den Data Science Bereich eine einfache Möglichkeit, Daten in Python einzulesen sowie zu manipulieren. Wer die Funktionsweise von NumPy verstanden hat, wird mit Pandas auch keine Probleme haben.

Übersicht der Datenstrukturen in Pandas

Bevor wir auf die verschiedenen Möglichkeiten mit Pandas zu arbeiten eingehen, möchten wir kurz eine Einführung in die verschiedenen Strukturen, die unsere Daten in Pandas haben können, geben. Hierbei gibt es drei verschiedene Möglichkeiten:

  • Series ( 1-Dimensional)
  • DataFrames ( 2-Dimensional)
  • Panels ( 3-Dimensional)

Liegen beispielsweise Zeitreihendaten vor, so kann es ebenso vorteilhaft sein, nur eine Series zu verwenden. Mit DataFrames haben wir in der Praxis am meisten zu tun, da sie einer typischen Tabelle bzw. n x m Matrix entsprechen. DataFrames vereinigen somit verschiedene Serien, sodass wir nicht nur einen Datenstrang repräsentieren können. Hierbei ist nun die Größe mutierbar, wobei die einzelnen Spalten logischerweise gleich langsein müssen. Mit DataFrames werden wir in diesem Artikel primär arbeiten.

DataFrames Beispiel

Panels ergänzen DataFrames wieder um eine weitere Dimension. Man kann sie sich somit als eine Sammlung von 2D-DataFrames vorstellen, wobei man sie aber in dieser Anordnung nicht wirklich visuell repräsentieren kann.

Installation und Erstellen eines DataFrames

Aber nun genug der Theorie! Pandas kann man wie jede andere Python Bibliothek über pip install pandas/ pip3 install pandas bzw. conda install pandas installieren. Der Import von Pandas erfolgt dann häufig mit der Abkürzung pd. Letztere ist sehr verbreitet und gibt jedem Data Scientist sofort die Information, dass in dem jeweiligen Skript mit Pandas gearbeitet wird.

import pandas as pd

Bevor wir darauf eingehen, wie man Datenformate mit Pandas einlesen kann, wollen wir kurz darstellen, wie man selbst einen DataFrame in Pandas erstellen kann. Ein DataFrame besteht aus zwei Bausteinen:

  1. Daten für die jeweiligen Spalten
  2. Spaltennamen

Die einfachste Möglichkeit zum Erstellen eines DataFrames ist die Übergabe der Daten in Form eines arrays und die Vorgabe der Spaltennamen (columns) wie im folgenden Beispiel zu sehen.

import numpy as np
import pandas as pd
df = pd.DataFrame(data=np.random.randn(5, 3),
                  columns=['Spalte 1', 'Spalte 2', 'Spalte 3'])

Alternativ ist es ebenso möglich einen DataFrame über ein Dictionary zu erstellen. In diesem Fall werden automatisch aus den Keys des Dictionaries, die Spaltennamen extrahiert:

df = pd.DataFrame(data={'Spalte 1': np.arange(start=10, stop=15),
                        'Spalte 2': np.arange(start=5, stop=10)})

Laden von Daten in Pandas

Da wir unsere Daten bekanntermaßen nicht alle manuell in Python eintragen wollen, existieren für die meisten populären Datenformate (*.csv, *.xlsx, *.dta, …) oder Datenbanken (SQL) bereits fertige Funktion in Pandas. Diese sind in den IO-Tools zusammengefasst. Einen Überblick findet ihr hier. Mit diesen Tools können nicht nur Daten eingelesen, sondern ebenfalls im passenden Format gespeichert werden. Die Funktionen sind vom Muster her alle sehr ähnlich und beginnen mit pd.read_..., worauf die jeweilige Spezifikation folgt. Beispielsweise für Excel-Dateien pd.read_excel()oder Stata pd.read_stata(). Um die verschiedenen Funktionen und Arbeitsweise mit und an einem DataFrame zu demonstrieren, nutzen wir den Titanic-Datensatz der Website Kaggle. Den Datensatz kann man auch über die Standford-Universität herunterladen. Nun laden wir einmal die Daten:

import pandas as pd
# Datensatz laden
df = pd.read_csv('.../titanic.csv')

Wie sind meine Daten aufgebaut?

Arbeitet man mit zunächst unbekannten Daten, kann man sich mit Pandas schnell einen Überblick über die Daten geben lassen, dabei greifen wir sowohl auf DataFrame-Eigenschaften wie auch Funktionen zu. Als kleine Checkliste sollen folgende Befehle dienen:

# Datenüberblick
df.shape
df.columns
df.head()
df.tail()
df.describe()

Mit df.shape fragen wir die Struktur des DataFrame ab, d.h. wie viele Spalten und Zeilen der DataFrame besitzt, in diesem Fall liegen 15 Spalten und 891 Zeilen bzw. Beobachtungen in dem Datensatz vor. Es ist also ein vergleichsweiser kleiner Datensatz. Mit df.columns kann man sich nun die Spaltennamen ausgeben lassen. Jetzt wissen wir zwar wie die Spalten heißen, aber nicht wie die Daten konkret aussehen, das kann man einfach mit der head oder tail-Funktion ändern. Mit diesen Funktionen werden im Normalfall die ersten fünf oder letzten fünf Zeilen des Datensatzes zurückgegeben. Über den Funktionsparameter n können auch mehr Zeilen zurückgegeben werden. Wie so ein DataFrame dann aussieht, seht ihr nun. Übersichtshalber sind hier nur die ersten fünf Spalten des Datensatz dargestellt, wenn ihr selbst die Funktion aufruft, werden deutlich mehr Spalte angezeigt.

Index survived pclass sex age sibsp
0 0 3 male 22 1
1 1 1 female 38 1
2 1 3 female 26 0
3 1 1 female 35 1
4 0 3 male 35 0

Anhand dieser ersten Übersicht erkennt man, dass unterschiedliche Skalen in den Daten enthalten sind. Die letzte Funktion, die wir nun vorstellen möchten, um einen ersten Eindruck über Daten zu gewinnen, ist describe. Mit dieser werden typische statistische Metriken wie der Durchschnitt und Median von denjenigen Spalten, die eine metrische Skala besitzen, zurückgegeben. Spalten wie z.B. die Spalte Geschlecht (sex) werden von dieser Funktion nicht berücksichtigt. Das Ergebnis gestaltet sich wie folgt:

survived pclass age sibsp parch fare
count 891 891 714 891 891 891
mean 0.383838 2.30864 29.6991 0.523008 0.381594 32.2042
std 0.486592 0.836071 14.5265 1.10274 0.806057 49.6934
min 0 1 0.42 0 0 0
25% 0 2 20.125 0 0 7.9104
50% 0 3 28 0 0 14.4542
75% 1 3 38 1 0 31
max 1 3 80 8 6 512.329

Neben den verschiedenen Metriken für die Spalten fällt doch deutlich auf, dass in der Spalte Alter (age) die Anzahl an Beobachtungen (count) von der Gesamtanzahl aller Beobachtungen abweicht. Um dieser Feststellung tiefer auf den Grund zu gehen, müssen wir uns die Spalte einmal genauer angucken.

Datenauswahl

Für die Auswahl von Spalten mit Pandas gibt es zwei Möglichkeiten:

# Spaltenauswahl
# 1. Moeglichkeit
df['age']
# 2. Moeglichkeit
df.age

Mit der ersten Möglichkeit kann man immer eine Spalte auswählen. Mit der zweiten Möglichkeit ist dies nicht immer garantiert, da Spaltennamen natürlich auch Leer- oder Sonderzeichen enthalten können. Führt man nun diesen Befehl aus, bekommt man eine Series als Ergebnis zurück, also ein nx1– Vektor. Dabei sieht man, dass einige Beobachtung fehlen und mit sogenannten NaN Werte versehen sind. Wie man die NaNs korrigieren kann, werden wir euch zum Ende des Artikels zeigen. Zunächst wollen wir noch darauf eingehen, wie man mehrere Spalten oder auch einen bestimmten Bereich eines DataFrame auswählen kann.

# Auswahl von mehreren Spalten
df[['age', 'sex']]
# Auswahl eines Bereichs auf Indexbasis
df.iloc[:2, :3]
# Auswahl eines Bereichs mit z.B. Spaltennamen
df.loc[:3, ['class', 'age']]

Die Auswahl von mehreren Spalten ist ebenso einfach möglich, dabei ist es wichtig zu beachten, dass man eine Liste der auszuwählenden Spaltennamen erstellt bzw. übergibt. Bei der Auswahl eines Ausschnittes des DataFrames bedient man sich der Funktionen iloc oder loc, erstere ist für eine indexbasierte Auswahl gedacht, d.h. man übergibt an die Funktion keine Spaltennamen, sondern die jeweilige Position der Spalte bzw. einen Bereich von Spalten bzw. Indizes. Bei der Funktion loc kann man dann wiederrum mit Listen und einzelnen Spaltennamen arbeiten. In dem obigen Beispiel würden so zunächst alle Zeilen bis zum Index 2 und die ersten drei Spalten ausgewählt werden. Bei dem loc-Beispiel werden hingegen Zeilen bis zum Index 3 in Verbindung mit den Spalten age und class ausgewählt. Mit diesen Funktionen schafft man einen Einstieg in die Auswahl von verschiedenen Datensätzen, die Beispiele kratzen nur an der Oberfläche der Möglichkeiten, wie man Daten auswählen kann.

Datenmanipulation

In der Praxis perfekt aufbereitete Daten vorzufinden, wäre eine super Sache, leider sieht die Realität dann doch etwas anders aus. Ein erstes Beispiel hatten wir bereits oben mit der Spalte age. Um unsere Daten später für Auswertungen oder Visualisierungen zu nutzen, wollen wir nun eine Möglichkeit darstellen, die Werte zu korrigieren. Hierzu bietet sich die Verwendung der fillna-Funktion an. Mit dieser werden die NaN-Werte automatisch ausgewählt und mit Werten, die man vorher festlegt hat, aufgefüllt. In unserem Fall füllen wir als Wert einfach das Durchschnittsalter auf. Wir fügen somit dem Alter keine Ausreißer hinzu und der Durchschnitt verändert sich nicht.

# Auffüllen von NaN-Werten
df.age.fillna(value=df.age.mean())

Nach Aufruf der Funktionen müssen wir natürlich noch die neue Altersspalte in unseren Datensatz einfügen, da ansonsten die Transformation nicht gespeichert wird. Die Zuweisung funktioniert sehr einfach, indem wir den neuen Spaltennamen so übergeben, als ob wir eine existierende Spalte auswählen würden. Im Anschluss kann man dann die neuen Werte einfach aufrufen. Alternativ könnte man die bisherige Altersspalte überschreiben, dies würde aber dazu führen, dass die Rohdaten nicht mehr ersichtlich wären.

# Zuweisen von neuen Werte zu einer Spalte / Erstellen einer neuen Spalte
df['age_new']=df.age.fillna(value=df.age.mean())

Zusammenfassung

Am Ende des Artikels wollen wir kurz noch wichtige Informationen über den Einstieg mit Pandas zusammenfassen:

  • Einlesen von Daten funktioniert einfach mit den Funktionen pd.read_..
  • Daten liegen in der Regel als zweidimensionaler DataFrame vor
  • Mit den Funktionen df.shape, df.head(), df.tail() und df.describe() erhält man einen ersten Überblick über die Daten
  • Spalten können sowohl einfach als auch mehrfach mit dem zugehörigen Namen ausgewählt werden
  • Bereiche eines DataFrame werden entweder mit iloc oder mit loc ausgewählt
  • Mit der Funktion fillna können fehlende Beobachtungen ersetzt werden

Diese Vorstellung stellt wie gesagt nur einen ersten Einstieg in die Bibliothek Pandas dar.

Als kleiner Ausblick in unseren nächsten Artikel in der Reihe Data Science mit Python werden wir uns dann mit der Visualisierungsbibliothek Matplotlib beschäftigen. Moritz Gnisia Moritz Gnisia

Mehr erfahren!

Als eines der führenden Beratungs- und Entwicklungs­unternehmen für Data Science und KI begleiten wir Unternehmen in die datengetriebene Zukunft. Erfahre mehr über statworx und darüber, was uns antreibt.
Über uns