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, ...).