Im ersten Teil dieser Serie haben wir uns bereits grundlegenden Pandas Objekten und deren Abfrage gewidmet. In diesem Kapitel beschäftigen wir uns darüber hinaus mit dem Umgang mit Pandas DataFrames. Als Ausgangsbeispiel nutzen wir den folgenden DataFrame.
# Import Module
import pandas as pd
import numpy as np
dates = pd.date_range("20220101", periods=6)
# Create DataFrame
df = pd.DataFrame(np.random.randn(6, 2), index=dates, columns=['column 1', 'column 2'])
df
Out:
column 1 column 2
2022-01-01 1.764052 0.400157
2022-01-02 0.978738 2.240893
2022-01-03 1.867558 -0.977278
2022-01-04 0.950088 -0.151357
2022-01-05 -0.103219 0.410599
2022-01-06 0.144044 1.454274
Wie löscht man leere Felder aus einem Pandas DataFrame?
Wenn wir einem DataFrame oder anderem Pandas Objekte leere Werte übergeben, werden diese automatisch durch Numpy NaNs (Not a Number) ersetzt. Für Kalkulationen, wie beispielsweise Mittelwertberechnungen, werden diese Felder nicht mit einbezogen und ignoriert. Den bestehenden DataFrame können wir einfach durch eine leere, dritte Spalte erweitern, die nur für den Index 01.01.2022 einen Wert enthält. Die restlichen Werte werden dann automatisch als NaN gesetzt.
df.loc['20220101', 'column 3'] = 1.0
df
Out:
column 1 column 2 column 3
2022-01-01 1.764052 0.400157 1.0
2022-01-02 0.978738 2.240893 NaN
2022-01-03 1.867558 -0.977278 NaN
2022-01-04 0.950088 -0.151357 NaN
2022-01-05 -0.103219 0.410599 NaN
2022-01-06 0.144044 1.454274 NaN
Wenn wir alle Zeilen löschen wollen, die mindestens in einer der Spalten einen leeren Wert haben, können wir das mit dem folgenden Befehl tun.
df.dropna(how="any")
Out:
column 1 column 2 column 3
2022-01-01 1.764052 0.400157 1.0
Wenn wir stattdessen Spalten mit Missing Values löschen wollen, nutzen wir dasselbe Kommando und setzen zusätzlich ‚axis = 1‘. Ansonsten können wir auch die leeren Felder mit vorgegebenen Werten füllen, beispielsweise mit dem Wert 0.
df.fillna(value=0)
Out:
column 1 column 2 column 3
2022-01-01 1.764052 0.400157 1.0
2022-01-02 0.978738 2.240893 0.0
2022-01-03 1.867558 -0.977278 0.0
2022-01-04 0.950088 -0.151357 0.0
2022-01-05 -0.103219 0.410599 0.0
2022-01-06 0.144044 1.454274 0.0
In manchen Fällen kann es auch sinnvoll sein, sich in den booleschen Werte (True/False) ausgeben zu lassen, an welcher Stelle Werte fehlen. In den meisten Fällen sind die DataFrame Objekte jedoch zu groß und dies ist keine übersichtliche Darstellung.
pd.isna(df)
Out:
column 1 column 2 column 3
2022-01-01 False False False
2022-01-02 False False True
2022-01-03 False False True
2022-01-04 False False True
2022-01-05 False False True
2022-01-06 False False True
Wie kann ich bestimmte Zeilen aus einem DataFrame löschen?
Wenn wir nicht nur leere Werte aus unserem DataFrame löschen wollen, gibt es zwei Möglichkeiten, wie wir das tun können. Zum einen können wir die Zeilen aus dem DataFrame löschen, indem wir den Index der Zeile nutzen, die gelöscht werden soll. In unserem Fall ist das ein konkretes Datum, wie beispielsweise der 01.01.2022:
df.drop(pd.to_datetime('2022-01-01'), axis=0)
Out:
column 1 column 2
2022-01-02 -0.497788 1.244450
2022-01-03 -0.429310 0.484361
2022-01-04 -0.929285 -0.222924
2022-01-05 0.656892 0.282631
2022-01-06 0.971478 -0.894619
Dadurch haben wir die erste Zeile in diesem Objekt gelöscht. In den meisten Fällen werden wir jedoch die konkrete Zeile noch nicht kennen, die wir löschen wollen. Dann können wir auch den DataFrame auf die Zeilen filtern, die wir löschen wollen und uns dann die Indexe der entsprechenden Rows ausgeben lassen.
df.drop(df[df['column 1'] > 0.1].index)
Out:
column 1 column 2
2022-01-01 -1.111707 -0.028735
2022-01-03 -1.791537 -0.279329
2022-01-05 -0.706618 -0.020599
2022-01-06 -1.212609 -2.467449
In diesem Fall löschen wir alle Zeilen für die gilt, dass in „column 1“ ein Wert größer als 0.1 erkannt wird. Dadurch bleiben insgesamt vier Zeilen im Objekt „df“ übrig.
Wie fügt man eine Spalte hinzu?
Auch hier gibt es mehrere Möglichkeiten den bestehenden DataFrame um neue Spalten zu erweitern. Indem wir die neue Spalte einfach mit eckigen Klammern definieren wird sie als neue Spalte an den DataFrame von rechts hinzugefügt.
df['column 3'] = np.random.randn(6, 1)
df
Out:
column 1 column 2 column 3
2022-01-01 0.478728 -0.740822 -0.871291
2022-01-02 -0.497788 1.244450 -0.299211
2022-01-03 -0.429310 0.484361 2.026658
2022-01-04 -0.929285 -0.222924 1.030583
2022-01-05 0.656892 0.282631 -0.158718
2022-01-06 0.971478 -0.894619 1.078394
Wenn wir stattdessen die neue Spalte an einem bestimmten Index einfügen wollen, können wir dafür „df.insert()“ nutzen:
df.insert(0,"new column 1", np.random.randn(6, 1), allow_duplicates = True)
df
Out:
new column 1 column 1 column 2
2022-01-01 0.566667 1.343228 -1.722417
2022-01-02 -0.450743 -1.390555 -1.013505
2022-01-03 -0.063856 1.269601 0.162296
2022-01-04 0.374292 -0.420009 0.130430
2022-01-05 0.723524 0.205791 -0.336845
2022-01-06 -0.262750 0.232997 -0.226452
Dieser Funktion übergibt man als ersten Wert den Index der neu einzufügenden Spalte, dann den Namen der Spalte und als drittes das Objekt, das als Spalte eingefügt werden soll. Der letzte Parameter gibt an, ob Duplikate dieser Spalte zugelassen werden. Wenn also die Spalte mit dem Namen und denselben Werten bereits existiert und „allow_duplicates“ auf „False“ gestellt wurde, dann erhält man eine Fehlernachricht.
Wie löscht man eine Spalte?
Wie bei jedem gutem Pandas Befehl, gibt es auch für das Löschen der Spalten verschiedene Möglichkeiten. Die beiden einfachsten sind entweder mithilfe der Funktion „df.drop()“ und dem Namen der Spalte, sowie „axis=1“ für eine Spaltenauswahl. Oder man nutzt die Python Standardfunktion „del“ und definiert die entsprechende Spalte:
df.drop('new column 1', axis=1)
del df['new column 1']
Zusammenführen von Pandas Objekten
Pandas bietet verschiedene Möglichkeiten, um Series oder DataFrame Objekte zusammenzuführen. Der concat-Befehl erweitert das erstgenannte Objekt um das zweitgenannte Objekt, wenn sie vom selben Typ sind. Der Befehl kann natürlich auch mit mehr als zwei Datenstrukturen ausgeführt werden.
s1 = pd.Series(['a', 'b'])
s2 = pd.Series(['c', 'd'])
pd.concat([s1, s2])
Out:
0 a
1 b
0 c
1 d
dtype: object
Mit DataFrames sieht die Codezeile genauso aus. Über den Zusatz ‚ignore_index‘ wird ein neuer durchgängiger Index vergeben und nicht der Index aus dem ursprünglichen Objekt übernommen.
df1 = pd.DataFrame([['a', 1], ['b', 2]],
columns=['letter', 'number'])
df1
Out:
letter number
0 a 1
1 b 2
df2 = pd.DataFrame([['c', 3], ['d', 4]],
columns=['letter', 'number'])
df2
Out:
letter number
0 c 3
1 d 4
pd.concat([df1, df2], ignore_index=True)
Out:
letter number
0 a 1
1 b 2
2 c 3
3 d 4
Pandas ermöglicht mit ‚Merge‘ zusätzlich auch Join-Möglichkeiten, wie sie den meisten wahrscheinlich aus SQL geläufig sind.
left = pd.DataFrame({"key": ["foo", "foo"], "lval": [1, 2]})
left
Out:
key lval
0 foo 1
1 foo 2
right = pd.DataFrame({"key": ["foo", "foo"], "rval": [4, 5]})
right
Out:
key rval
0 foo 4
1 foo 5
pd.merge(left, right, on='key')
Out:
key lval rval
0 foo 1 4
1 foo 1 5
2 foo 2 4
3 foo 2 5
Wenn wir statt Left- bzw. Right Joins einen Inner Join durchführen wollen, nutzen wir wieder den Concat Befehl mit dem Zusatz ‚join = „inner“‚.
pd.concat([left, right], join="inner")
Out:
key
0 foo
1 foo
0 foo
1 foo
Das solltest Du mitnehmen
- Pandas bietet viele Möglichkeiten mit Missing Values umzugehen. Man kann die betreffenden Spalten/Zeilen entweder streichen oder die Felder mit einem Wert ersetzen.
- Mit Pandas haben wir dieselben Join Möglichkeiten wie mit SQL.