Python: Wie benennt man Spalten in einem Pandas-DataFrame um?
Spalten umzubenennen ist meistens das Erste, was man nach dem Einlesen einer fremden CSV tut. Es gibt zwei Wege, sie verhalten sich bei Fehlern unterschiedlich, und einer davon scheitert ohne es zu sagen.
Einzelne umbenennen
df = df.rename(columns={"a": "alpha"})
before : ['a', 'b', 'c']
after : ['alpha', 'b', 'c']
original untouched : ['a', 'b', 'c'] <- rename returns a copy
rename
nimmt eine Zuordnung von altem zu neuem Namen entgegen, lässt alles andere in
Ruhe und liefert ein neues DataFrame zurück.
Alle umbenennen
df.columns = ["x", "y", "z"]
['x', 'y', 'z']
Das geht über die Position und verändert das DataFrame direkt. Es besteht auf der richtigen Anzahl:
wrong length -> ValueError: Length mismatch: Expected axis has 3 elements, new values have 2 elements
Ein nützliches Sicherheitsnetz — und das Gegenteil davon, wie sich rename
verhält.
Das stille Scheitern
Hier ist das, was man über rename wissen sollte:
df.rename(columns={"typo": "alpha"})
['a', 'b', 'c']
Es ist nichts passiert. Kein Fehler, keine Warnung, keine Änderung. Eine Spalte
namens typo gibt es nicht, die Zuordnung hat also nichts getroffen, und
rename hat vergnügt eine Kopie dessen zurückgegeben, was du hineingegeben
hast.
Für den vorgesehenen Zweck ist das in Ordnung — du darfst eine Zuordnung
übergeben, die Spalten enthält, die es geben kann oder auch nicht. Es heißt
aber, dass ein Tippfehler im alten Namen unsichtbar bleibt. In einer
Verarbeitungskette zeigt sich der Fehler später als KeyError auf einer
Spalte, von der du sicher warst, sie umbenannt zu haben.
Verlang die Prüfung:
df.rename(columns={"typo": "alpha"}, errors="raise")
-> KeyError: "['typo'] not found in axis"
Ich würde errors="raise" grundsätzlich setzen und nur dort weglassen, wo eine
unvollständige Zuordnung Absicht ist.
inplace und das None, das zurückkommt
ergebnis = df.rename(columns={"a": "alpha"}, inplace=True)
return value of inplace=True : None
df.columns after : ['alpha', 'b', 'c']
Das Umbenennen hat stattgefunden, und der Rückgabewert ist None. Diese
verbreitete Form:
df = df.rename(columns={...}, inplace=True) # df ist jetzt None
ersetzt dein DataFrame also durch None. Entweder du verwendest inplace=True
als Anweisung, oder du lässt es weg und weist das Ergebnis zu. Nicht beides.
Beachte, dass pandas sich generell von inplace wegbewegt — es spart selten
Speicher und verhindert das Verketten von Methoden, die Zuweisungsform ist also
ohnehin vorzuziehen.
Unordentliche Namen aufräumen
rename nimmt auch eine Funktion entgegen, die auf jede Spalte angewendet wird:
df.rename(columns=str.lower)
before : ['First Name', 'Last Name']
after : ['first name', 'last name']
Für ein richtiges Aufräumen ein Lambda:
df.rename(columns=lambda c: "_".join(c.lower().split()))
lower + collapse spaces : ['first_name', 'last_name']
.split() ohne Argument trennt an Folgen von Leerraum, das doppelte Leerzeichen
in Last Name fällt also zusammen, statt zu einem doppelten Unterstrich zu
werden.
Dasselbe über den Index, was sich bei einer Kette von String-Operationen oft besser liest:
df.columns = df.columns.str.lower().str.replace(r"\s+", "_", regex=True)
['first_name', 'last_name']
Dubletten sind erlaubt und ändern, was beim Indizieren herauskommt
pandas hindert dich nicht daran, eine Spalte auf den Namen einer anderen umzubenennen:
after renaming 'a' to 'b' : ['b', 'b', 'c']
Zwei Spalten heißen b. Keine Warnung. Und jetzt:
df['b'] now returns DataFrame with shape (1, 2)
df["b"] hat vorher eine Series geliefert und liefert jetzt ein DataFrame.
Jeder nachgelagerte Code, der eine Series erwartet hat — .str, .mean(), ein
Vergleich mit einem Skalar — verhält sich anders oder bricht.
Wenn du aus einer zur Laufzeit gebauten Zuordnung umbenennst, lohnt sich
anschließend ein df.columns.duplicated().any().
Der Rest der Familie
set_axis(['x','y','z'], axis=1) : ['x', 'y', 'z']
add_prefix('col_') : ['col_a', 'col_b', 'col_c']
add_suffix('_raw') : ['a_raw', 'b_raw', 'c_raw']
set_axis ist die verkettbare Fassung der Zuweisung an .columns, was zählt
wenn du eine Verarbeitungskette als einen Ausdruck baust. add_prefix und
add_suffix sind vor einem Merge nützlich, um zwei Sätze ähnlich benannter
Spalten auseinanderzuhalten.
Und rename benennt den Index auf genau dieselbe Weise um:
df.rename(index={'r1': 'first'}) : ['first', 'r2']
axis=1 ist eine andere Schreibweise für columns=, falls dir die Symmetrie
mit dem Rest der pandas-Schnittstelle lieber ist.
Hinweis zu Netcup (Werbung)
Der deutsche Hoster Netcup bietet unter anderem günstige und zugleich leistungsstarke Webhosting Pakete, KVM-basierte Root Server und dezidierte Server an. Mit unseren Gutscheincodes kannst du noch mehr Geld sparen (6€ bei deiner ersten Bestellung, 30% Rabatt auf alle KVM-basierten Root Server, ...).