Pandas erlaubt wie NumPy vektorisierte Operationen, dass heißt, Berechnungen mit einer Series oder einem DataFrame werden auf jedes Element angewendet. So können die Rechenoperatoren direkt verwendet werden.
print("Temperaturen in Celsius:")print(27*"=")print(temperaturen, "\n")print("Temperaturen in Fahrenheit:")print(27*"=")print(temperaturen *9/5+32)
Temperaturen in Celsius:
===========================
2021 2022 2023 2024
Jan 2 3 -3 -1
Feb 4 6 -1 2
Mär 7 9 4 5
Apr 12 13 9 8
Mai 19 18 15 17
Jun 23 21 20 24
Jul 25 24 20 25
Aug 23 23 19 20
Sep 18 19 16 17
Okt 15 14 15 14
Nov 9 8 7 9
Dez 5 4 6 2
Temperaturen in Fahrenheit:
===========================
2021 2022 2023 2024
Jan 35.6 37.4 26.6 30.2
Feb 39.2 42.8 30.2 35.6
Mär 44.6 48.2 39.2 41.0
Apr 53.6 55.4 48.2 46.4
Mai 66.2 64.4 59.0 62.6
Jun 73.4 69.8 68.0 75.2
Jul 77.0 75.2 68.0 77.0
Aug 73.4 73.4 66.2 68.0
Sep 64.4 66.2 60.8 62.6
Okt 59.0 57.2 59.0 57.2
Nov 48.2 46.4 44.6 48.2
Dez 41.0 39.2 42.8 35.6
Auch boolsche Operationen können direkt ausgeführt werden.
Pandas umfasst eine Vielzahl von Methoden, die arithmetische, summarische, boolsche und Indexfunktionen umsetzen. Eine vollständige Übersicht finden Sie hier: https://pandas.pydata.org/docs/reference/index.html.
In der Regel werden die Funktionen standardmäßig spaltenweise angewendet. Mit dem Argument axis = 1 wird die jeweilige Funktion zeilenweise ausgeführt. Die Funktionen sind auch für Series verfügbar.
Im Folgenden werden einige Methoden exemplarisch vorgestellt.
arithmetische Funktionen
Die Methoden pd.DataFrame.add(), pd.DataFrame.sub(), pd.DataFrame.mul(), pd.DataFrame.div(), pd.DataFrame.floordiv(), pd.DataFrame.mod() und pd.DataFrame.pow() entsprechen den Grundrechenarten mit den Operatoren +, -, *, /, //, %, **. Sie eignen sich gut für verkettete Operationen.
print("Temperaturen in Fahrenheit:")print(27*"=")print(temperaturen.mul(9).div(5).add(32))
Temperaturen in Fahrenheit:
===========================
2021 2022 2023 2024
Jan 35.6 37.4 26.6 30.2
Feb 39.2 42.8 30.2 35.6
Mär 44.6 48.2 39.2 41.0
Apr 53.6 55.4 48.2 46.4
Mai 66.2 64.4 59.0 62.6
Jun 73.4 69.8 68.0 75.2
Jul 77.0 75.2 68.0 77.0
Aug 73.4 73.4 66.2 68.0
Sep 64.4 66.2 60.8 62.6
Okt 59.0 57.2 59.0 57.2
Nov 48.2 46.4 44.6 48.2
Dez 41.0 39.2 42.8 35.6
Außerdem kann mit dem Parameter fill_value ein Füllwert für fehlende Werte spezifiziert werden (dieser wird vor der Operation eingesetzt). Wie NumPys np.nan umfasst auch Pandas einen speziellen fehlenden Wert: pd.NA (achten Sie auf den Datentyp der Ausgabe). Der Umgang mit fehlenden Werten wird ausführlich im Methodenbaustein Einlesen strukturierter Datensätze behandelt.
Mittlere Jahrestemperaturen
===========================
2021 13.500000
2022 13.500000
2023 10.583333
2024 11.833333
dtype: float64
Monatliche Mindesttemperatur
============================
Jan -3
Feb -1
Mär 4
Apr 8
Mai 15
Jun 20
Jul 20
Aug 19
Sep 16
Okt 14
Nov 7
Dez 2
dtype: int64
boolsche Funktionen
Pandas bietet wie die Pythonbasis verschiedene boolsche Funktionen.
pd.DataFrame.isin(values) prüft für jedes Element des DataFrame, ob dieses in values enthalten ist. Mit dem Operator ~ kann geprüft werden, ob die Elemente eines DataFrame nicht in values enthalten sind: ~pd.DataFrame.isin(values).
Die Funktionsausführung ist abhängig vom Datentyp des in values übergebenen Objekts.
Wenn values eine Liste oder ein NumPy-Array ist, ist das Ergebnis True, wenn es eine Übereinstimmung mit einem der enthaltenen Elemente gibt.
Ist value eine Series oder ein DataFrame, wird die Übereinstimmung positionsbasiert überprüft (siehe Beispiel).
Beispiel 2.1: klassenabhängige Funktionsausführung
Eine klassenabhängige Funktionsausführung kann, wenn das Verhalten unbemerkt bleibt, die Ergebnisse einer Datenanalyse verfälschen. Um dies zu verhindern, sollten Sie 3 allgemeine Ratschläge befolgen:
Schauen Sie in die Dokumentation der jeweiligen Funktion. Python und viele Module entwickeln sich dynamisch, sodass sich das Verhalten einer Funktion verändern kann.
Gehen Sie schrittweise vor und lassen sich die Zwischenergebnisse von Arbeitsschritten mit der Funktion print() ausgeben.
Bei großen Datenmengen ist es häufig einfacher, mit eigens erzeugten Testdaten zu arbeiten. Ein zehnzeiliger DataFrame mit den Datentypen und der Struktur der Arbeitsdaten, ist leichter zu überblicken. Nutzen Sie einen solchen Testdatensatz um die von Ihnen verwendeten Funktionen zu überprüfen.
Eine Gruppe von Funktionen setzt logische Vergleiche um.
2021 2022 2023 2024
Jan True False True True
Feb False False True True
Mär False False False False
Apr False False False False
Mai False False False False
Jun False False False False
Jul False False False False
Aug False False False False
Sep False False False False
Okt False False False False
Nov False False False False
Dez False False False True
Jan False
Feb False
Mär True
Apr True
Mai True
Jun True
Jul True
Aug True
Sep True
Okt True
Nov True
Dez False
Name: 2021, dtype: bool
Verwendung der Methoden .agg() und .apply()
Pandas bringt zwei eigene Methoden mit, um Operationen zeilen- oder spaltenweise auszuführen. DataFrame.agg() (oder auch DataFrame.aggregate()) aggregiert einen DataFrame zeilen- oder spaltenweise durch eine Funktion. Die Pandas-Methode DF.apply() wendet eine Funktion zeilen- oder spaltenweise auf einen DataFrame an. Die Methoden sind also sehr ähnlich und führen in den meisten Fällen zum selben Ergebnis.
Beide Funktionen führen mit dem Argument axis = 1 Operationen zeilenweise aus.
Besonders nützlich ist die Möglichkeit, Funktionen, die normalerweise auf eine Series angewendet werden, auf jedes Element der Series anzuwenden. Dafür wird die lambda Syntax verwendet: lambda x: x + 1. lambda ist ein Platzhalter und kann als “für jedes x tue:” gelesen werden. So kann beispielsweise die Anzahl der Zeichen in jeder Zeile bestimmt werden.
# Auf die Series angewendetprint(len(str(temperaturen[2021])), "\n")# Elementweise angewendetprint(temperaturen[2021].agg(lambda x: len(str(x))), "\n") # deprecatedprint(temperaturen[2021].apply(lambda x: len(str(x))), "\n")
144
Jan 1
Feb 1
Mär 1
Apr 2
Mai 2
Jun 2
Jul 2
Aug 2
Sep 2
Okt 2
Nov 1
Dez 1
Name: 2021, dtype: int64
Jan 1
Feb 1
Mär 1
Apr 2
Mai 2
Jun 2
Jul 2
Aug 2
Sep 2
Okt 2
Nov 1
Dez 1
Name: 2021, dtype: int64
Details zur Verwendung des Lambda-Ausdrucks finden Sie in der Dokumentation.
Der Vollständigkeit wegen ist zu erwähnen, dass mit den Methoden .map() und .transform() weitere, sehr ähnliche Alternativen bestehen. Bei Interesse können Sie die Unterschiede in diesem Artikel nachlesen.
Um die Indexposition eines bestimmten Werts zu bestimmen, kann die Numpy-Funktion np.where() verwendet werden. Diese gibt zwei Arrays mit den jeweiligen Zeilen- und Spaltennummern zurück.
print(np.where(temperaturen ==4))
(array([ 1, 2, 11]), array([0, 2, 1]))
Unter anderem befindet sich der Wert 4 in Zeile 1 in Spalte 0 oder auch in Zeile 2 in Spalte 2.
Pandas bietet zwei Methoden, um Werte zu ersetzen.
pd.DataFrame.replace(to_replace, value, *, inplace = False) ersetzt to_replace mit value. Mit dem Argument inplace = True erfolgt dies direkt im Objekt.
pd.where(cond, other = nan, inplace = False) behält cond und ersetzt alle anderen Werte mit other (standardmäßig ein Platzhalter für fehlende Werte). Mit dem Argument inplace = True erfolgt dies direkt im Objekt.
Die Syntax beider Funktionen unterscheidet sich leicht, wie im folgenden Beispiel zu sehen ist.
print(temperaturen.replace(to_replace =25, value =1000), "\n")print(temperaturen.where(temperaturen ==25, other =1000))
Die Methode DataFrame.sort_index(axis = 0, ascending = True, inplace = False) sortiert entlang einer Achse, standardmäßig aufsteigend nach dem Index. Durch die Übergabe des Arguments axis = 1 werden die Spalten sortiert. Mit dem Argument ascending = False wird absteigend sortiert. Das Argument inplace = True sorgt, wie gewohnt, dafür, dass das Ergebnis des Sortiervorgangs direkt im Objekt gespeichert wird.
Die Methode DataFrame.sort_values(by, *, axis = 0, ascending = True, inplace = False) sortiert Werte entlang einer Achse, standardmäßig entlang des Index (axis = 0). Dem Parameter by sind laut Dokumentation der Spaltenname als string bzw. eine Liste von Spaltennamen als string zu übergeben, nach denen sortiert werden soll. Wie im folgenden Code-Beispiel zu sehen ist, muss die numerische Spaltenbeschriftung jedoch auch in numerischer Form übergeben werden.
Wird mit dem Argument axis = 1 entlang der zweiten Dimension sortiert, werden entsprechend Indexbeschriftungen übergeben.
# Sortieren nach numerischen Spaltenbeschriftungenprint(temperaturen.sort_values(by =2021), "\n")print(temperaturen.sort_values(by = [2021, 2023]), "\n")# Sortieren nach als string übergebenen Spaltenbeschriftungen# führt zu KeyError, die Fehlermeldung wird nicht vollständig abgefangentry:print(temperaturen.sort_values(by ='2021'))exceptExceptionas error:print(error)
Sortieren Sie den DataFrame ‘meerschweinchen’ absteigend nach der Zahnlänge (‘len’). Welches Meerschweinchen hat die längste zahnbildende Zelle (gesucht ist die ID)?
Welches Meerschweinchen, welches die Dosis 1.0 erhielt, hat die längste zahnbildende Zelle (gesucht ist die ID)?
ID len supp dose
49 50 27.3 OJ 1.0
43 44 26.4 OJ 1.0
46 47 25.8 OJ 1.0
45 46 25.2 OJ 1.0
42 43 23.6 OJ 1.0
Die ID lautet: 50
2.7 GroupBy
Die Methode pd.groupby() teilt einen DataFrame (oder eine Series) in Gruppen auf und gibt ein GroupBy-Objekt zurück. Das GroupBy-Objekt hat dieselben Spalten- und Zeilenbeschriftungen wie der DataFrame, das GroupBy-Objekt ist aber nach der Gruppenaufteilung sortiert. Operationen, die auf das GroupBy-Objekt angewendet werden, werden für jede Gruppe separat ausgeführt.
Dies kann am Datensatz ‘meerschweinchen’ im folgenden Panel nachvollzogen werden.
Reiter: Der Datensatz enthält 60 Einträge. Die ersten 30 Einträge haben in der Spalte ‘supp’ die Ausprägung VC für Vitamin C, die letzten 30 Einträge die Ausprägung OJ für Orangensaft.
Reiter: Mit der Methode pd.groupby('supp') kann der Datensatz nach den Merkmalsausprägungen in der Spalte ‘dose’ (0.5, 1 und 2) gruppiert werden.
Reiter: Auf das Groupby-Objekt können Operationen ausgeführt werden. Beispielsweise kann die Spalte ‘len’ ausgewählt und mit der Methode .mean() die mittlere Länge der zahnbildenden Zelle bestimmt werden.
Reiter: Ebenso kann nach den Ausprägungen mehrerer Merkmale gruppiert werden, indem diese als Liste übergeben werden pd.groupby(by = ['supp', 'dose']).
Für die Methode .head() wurde das Argument n halbiert, um die gleiche Zeilenzahl in der Ausgabe anzeigen zu lassen, da auch diese Methode für jede der beiden Gruppen (VC und OJ) ausgeführt wird.
Henderson and Velleman 1981. Building multiple regression models interactively. Biometrics 37: 391–411. Der Datensatz ist abrufbar auf GitHub und in R verfügbar.
Gruppieren Sie den Datensatz nach der Anzahl Zylinder und ermitteln Sie den durchschnittlichen Kraftstoffverbrauch für jede Gruppe.
Wie viele Liter auf 100 Kilometer sind es?
Gruppieren Sie den Datensatz nach der Anzahl der Zylinder und der Vergaser. Welche Gruppe ist am schnellsten auf der Viertelmeile?