Skip to content

pandas 3.1 Upgrade: Pandas4Warning für inplace beheben, df.select() und pd.col() nutzen, read_csv schneller machen

Aktualisiert am

pandas 3.1.0 (22. Oktober 2026) markiert inplace=True bei drop, rename, sort_values und acht weiteren Methoden als deprecated, bringt DataFrame.select() mit pd.col()-Ausdrücken und filter(cond=) und liest große CSV-Dateien parallel. Auf macOS getestet: Eine 72-MB-CSV ging von 0,23 s auf 0,02 s, die genaue Pandas4Warning-Liste, die read_csv-Optionen, die den parallelen Reader still abschalten, und die NumPy-2.3.3-Falle unter Python 3.14.

Die kurze Antwort: pandas 3.1.0 ist am 22. Oktober 2026 erschienen, das Bugfix-Release 3.1.1 folgte am 4. November. Upgraden Sie direkt auf 3.1.1:

pip install --upgrade "pandas>=3.1"
# or, in a uv project
uv add "pandas>=3.1"

Nach dem Upgrade passieren drei Dinge:

  1. Ihr Code gibt Pandas4Warning aus, und zwar für jedes inplace=True bei drop, rename, reset_index, set_index, sort_values, dropna, drop_duplicates und einigen weiteren Methoden. Die Lösung ist mechanisch: df = df.drop(...) statt df.drop(..., inplace=True). Oft kommt die Warnung aus einer Bibliothek, die Sie nutzen, nicht aus Ihrem eigenen Code.
  2. pd.read_csv wird bei großen lokalen Dateien deutlich schneller. Eine 72-MB-Datei ging in unserem Test von 0,23 s auf pandas 3.0.1 auf 0,02 s auf 3.1. Einige gängige Argumente schalten die Beschleunigung ab; sie sind unten aufgelistet.
  3. Sie bekommen eine API im Polars-Stil: df.select("a", pd.col("b") * 2) und df.filter(pd.col("a") > 1).

Wenn Sie noch auf pandas 2.x sind, ist der Sprung auf 3.x (Copy-on-Write, der Standard-String-Dtype) die größere Änderung, und der pandas 3.0 Migration Guide (opens in a new tab) ist der richtige Einstieg. Diese Anleitung behandelt 3.0 → 3.1 und die Fallen, in die wir getreten sind.

Was getestet wurde: Alles, was unten als „getestet“ markiert ist, lief am 1. November 2026 auf einem Apple M4 Max (16 Kerne, macOS) in einer frischen uv-Umgebung mit CPython 3.14.2, pandas 3.1.0, NumPy 2.5.4 und PyArrow 26.0.0. Die Vergleichszahlen stammen von pandas 3.0.1 mit NumPy 2.4.2 und ohne PyArrow auf derselben Maschine. Das Verhalten unter Windows, Linux, conda und Docker stammt aus der offiziellen Dokumentation und wurde hier nicht getestet. Am 4. November 2026 wurden alle getesteten Aussagen mit pandas 3.1.1 erneut geprüft, mit denselben Ergebnissen.

Was sich in 3.1 spürbar ändert

ÄnderungWas das für Sie bedeutetAktion
inplace deprecated bei 11 Methoden (PDEP-8)Jeder Aufruf gibt eine Pandas4Warning aus; in pandas 4.0 wird der Parameter entferntErgebnis zuweisen: df = df.drop(...)
Paralleles read_csv für lokale, unkomprimierte Dateien ≥ 5 MB2–3x schneller im Single-Thread, dazu standardmäßig bis zu 6 ThreadsNichts, außer Sie übergeben usecols, index_col, nrows oder ein File-Handle (siehe unten)
DataFrame.select() (nimmt pd.col()-Ausdrücke, verfügbar seit 3.0)Spalten in einem Aufruf auswählen und berechnen, Polars-StilOptional; nützlich in Methodenketten
filter(cond=...) akzeptiert eine boolesche Maskedf.filter(pd.col("a") > 1) behält ZeilenAchtung: Eine positionale Liste von Booleans wählt weiterhin Labels aus
NumPy ≥ 2.0.2 erforderlich (≥ 2.3.3 unter Python 3.14)Umgebungen mit NumPy 1.x können 3.1 nicht installierenErst NumPy upgraden oder pandas<3.1 pinnen
Numerische Eingaben werden standardmäßig Mikrosekundenpd.to_timedelta([1], unit="s") ist jetzt timedelta64[us], nicht [s]Behebt einen Rundungsfehler aus 3.0; .as_unit() nutzen, wenn Sie eine bestimmte Auflösung brauchen
dtype="category" in read_csv erkennt numerische KategorienPostleitzahlen und IDs verlieren führende NullenDiese Spalten zuerst als str lesen

Die vollständige Liste steht im offiziellen What's new in 3.1.0 (opens in a new tab). Der Rest dieser Anleitung geht die Aufgaben der Reihe nach durch: installieren, die Warnungen beheben, die neue API nutzen, das CSV-Laden beschleunigen und die Verhaltensänderungen prüfen, die Ergebnisse ohne Fehlermeldung verändern können.

Schritt 1: pandas 3.1 installieren

Voraussetzungen (getestet)

pandas 3.1.0 liefert Wheels für CPython 3.11 bis 3.15 (requires_python >= 3.11) und ist sowohl auf PyPI als auch auf conda-forge verfügbar. Die NumPy-Untergrenze hängt von Ihrer Python-Version ab:

PythonMinimales NumPy
3.11 – 3.132.0.2
3.14 – 3.152.3.3

Die Whatsnew-Seite nennt nur 2.0.2. Unter Python 3.14 verlangen die Wheel-Metadaten 2.3.3, und genau das setzt der Resolver durch. Ein Pin auf NumPy 1.x scheitert sofort:

  × No solution found when resolving dependencies:
  ╰─▶ Because pandas==3.1.1 depends on numpy>=2.3.3 and you require
      pandas==3.1.1, we can conclude that you require numpy>=2.3.3.
      And because you require numpy<2, we can conclude that your requirements
      are unsatisfiable.

Wenn eine Abhängigkeit noch numpy<2 pinnt, blockiert diese Abhängigkeit das Upgrade, nicht pandas. Aktualisieren Sie sie oder bleiben Sie bei pandas<3.1, bis sie nachzieht.

Upgrade (getestet mit uv)

Installieren Sie 3.1.1, nicht 3.1.0: 3.1.1 behebt eine Regression, bei der read_csv und to_csv Pfadobjekte wie tmpdir aus pytest als offene File-Handles behandelten und dadurch Fehler werfen oder unvollständige Dateien schreiben konnten (What's new in 3.1.1 (opens in a new tab)).

# pip
pip install --upgrade "pandas>=3.1,<3.2"
 
# uv project
uv add "pandas>=3.1,<3.2"
 
# uv, throwaway environment to test first
uv venv p31 --python 3.14
uv pip install --python p31/bin/python "pandas==3.1.1" pyarrow
p31/bin/python -c "import pandas as pd; print(pd.__version__)"

conda-forge hat 3.1.1 (geprüft am 4. November 2026; conda install -c conda-forge "pandas>=3.1"), hier nicht getestet.

Installieren Sie auch PyArrow, falls noch nicht geschehen. pandas 3 nutzt es für den Standard-String-Dtype, wenn es vorhanden ist, und der CSV-Reader mit engine="pyarrow" braucht es.

Schritt 2: Die Pandas4Warning für inplace beheben

Nach dem Upgrade gibt Code wie dieser:

df.drop(columns=["rain"], inplace=True)

Folgendes aus:

Pandas4Warning: The inplace keyword in DataFrame.drop is deprecated and will be removed in a future version (PDEP-8).
See https://pandas.pydata.org/docs/dev/whatsnew/v3.1.0.html#deprecation-inplace for more details.

Welche Methoden betroffen sind (getestet)

Die Deprecation betrifft Methoden, bei denen inplace=True nie Werte an Ort und Stelle verändert hat. Bei dropna, sort_values und den anderen Methoden, die Zeilen umordnen, war es immer eine Neuzuweisung, und die Kopie, die drop, rename oder set_index früher vermieden haben, entsteht unter Copy-on-Write, das mit pandas 3.0 kam, ohnehin nicht mehr.

Methodeinplace in 3.1Lösung
drop, rename, rename_axisDeprecateddf = df.drop(...)
reset_index, set_indexDeprecateddf = df.reset_index()
sort_values, sort_indexDeprecateddf = df.sort_values("col")
dropna, drop_duplicatesDeprecateddf = df.dropna()
eval, queryDeprecateddf = df.query("a > 1")
fillna, replace, where, mask, clip, interpolateBleibt (sie können Werte wirklich in place ändern)Keine Änderung nötig

In unserem Test warnten alle 11 deprecated Methoden beim Aufruf mit inplace=True; fillna und replace nicht, wie dokumentiert.

Der Ersatz ist eine Ein-Zeilen-Änderung pro Aufruf:

# before
df.rename(columns={"temp": "temp_c"}, inplace=True)
df.sort_values("temp_c", inplace=True)
df.reset_index(drop=True, inplace=True)
 
# after (same cost, chains cleanly)
df = (
    df.rename(columns={"temp": "temp_c"})
      .sort_values("temp_c")
      .reset_index(drop=True)
)

Jeden Aufruf im eigenen Code finden (getestet)

Machen Sie die Warnung für einen Durchlauf zum Fehler, dann zeigt der Traceback auf die exakte Zeile. python -W akzeptiert keine Klasse aus einem Drittpaket wie pandas.errors.Pandas4Warning: Es gibt Invalid -W option ignored: invalid module name: 'pandas.errors' aus und führt das Skript trotzdem aus. Filtern Sie stattdessen nach der Meldung:

python -W "error:The inplace keyword:DeprecationWarning" your_script.py

Um jede Pandas4Warning zum Fehler zu machen, nicht nur die für inplace:

python -c "import runpy, warnings, pandas as pd; warnings.simplefilter('error', pd.errors.Pandas4Warning); runpy.run_path('your_script.py', run_name='__main__')"

Beide brechen mit einem Traceback an der ersten inplace-Zeile ab. Der Meldungsfilter lässt andere Deprecation-Warnungen in Ruhe.

Bei einer Testsuite wendet pytest seine -W-Filter erst an, wenn pandas importierbar ist, deshalb funktioniert der Klassenname dort:

pytest -W error::pandas.errors.Pandas4Warning

Pandas4Warning ist eine Unterklasse von PandasDeprecationWarning, ein Filter auf eine der beiden funktioniert also. Ein grep bringt Sie ebenfalls weit:

grep -rn "inplace=True" --include="*.py" --include="*.ipynb" .

Wenn die Warnung aus einer Bibliothek kommt, nicht von Ihnen

Das ist in den ersten Wochen nach einem Release der häufigste Fall. Zwischen dem 22. Oktober und dem 1. November 2026 kamen auf GitHub etwa 300 Issues und Pull Requests dazu, die Pandas4Warning erwähnen, und etwa 3.500, die „pandas 3.1“ erwähnen, in Projekten wie yfinance (29 inplace-Aufrufe in 8 Dateien, yfinance #3009 (opens in a new tab); behoben in yfinance 1.8.0 am 3. November), FLAML, marimo, cuDF, darts und category_encoders.

Das können Sie aus Ihrem Code heraus nicht beheben. Optionen, in dieser Reihenfolge:

  1. Die Bibliothek aktualisieren. Viele haben innerhalb weniger Tage Fixes veröffentlicht.
  2. Nur diese eine Warnungsklasse stummschalten, bis die Bibliothek nachzieht, statt alle Warnungen:
import warnings
import pandas as pd
 
warnings.filterwarnings("ignore", category=pd.errors.Pandas4Warning)
  1. pandas<3.1 pinnen in der Umgebung, in der die ungepflegte Bibliothek läuft. Pinnen Sie pandas 3.0 aber nicht für immer; das inplace-Schlüsselwort wird in 4.0 entfernt, und die Warnung ist Ihre Vorlaufzeit.

Weitere Deprecations, die Ihnen in 3.1 begegnen können (getestet, sofern nicht anders angegeben)

Code, der jetzt warntErsatz
s.dt.dayofweek, .dayofyear, .daysinmonths.dt.day_of_week, .day_of_year, .days_in_month
df.select_dtypes(include="object") auf String-Spalten (warnte schon in 3.0; 3.1 ergänzt exclude="object")"str" explizit übergeben; "object" bedeutet in pandas 3 nicht mehr „Text“
s.fillna("missing") auf einer Float-SpalteZuerst in einen gemeinsamen Dtype casten; das wird in einer künftigen Version einen Fehler werfen
ser.values auf einer Spalte mit Zeitzoneser.array, ser.to_numpy() oder ser.dt.tz_convert(None).to_numpy(), um das alte UTC-Array zu behalten
pd.infer_freq(idx) gibt "D" zurückWird ein Offset-Objekt zurückgeben; .freqstr nutzen oder future.infer_freq_returns_offset setzen
read_parquet(engine="fastparquet") (Doku)fastparquet ist eingestellt; die Standard-Engine PyArrow nutzen
pd.set_eng_float_format() (Doku)pd.set_option("display.precision", n)

Schritt 3: df.select(), pd.col() und filter(cond=) nutzen

DataFrame.select() und filter(cond=) sind die sichtbare neue API in 3.1. pd.col() selbst kam schon mit pandas 3.0 für assign() und .loc; in 3.1 wird es zum natürlichen Argument für beide neuen Methoden. Wer Polars kennt, wird sie wiedererkennen.

select wählt und berechnet Spalten in einem Aufruf (getestet)

import pandas as pd
 
df = pd.DataFrame({
    "city": ["Tokyo", "Seoul", "Osaka"],
    "temp": [18.2, 15.1, 19.5],
    "rain": [12, 30, 8],
})
 
df.select("city", "temp")                         # same as df[["city", "temp"]]
df.select("city", temp_f=pd.col("temp") * 1.8 + 32)   # keyword names the new column
    city  temp_f
0  Tokyo   64.76
1  Seoul   59.18
2  Osaka   67.10

Spätere Argumente können sich auf Spalten beziehen, die früher im selben Aufruf erzeugt wurden, wie bei assign:

df.select(temp_c=pd.col("temp"), temp_f=pd.col("temp_c") * 1.8 + 32)

pd.col("temp") ist eine pandas.api.typing.Expression. Sie unterstützt die Operatoren und Accessoren, die Sie auf einer Series nutzen würden, einschließlich .str und .round():

df.select(pd.col("city").str.upper(), pd.col("temp").round(0))

Drei Dinge, über die wir gestolpert sind (getestet):

  • Es gibt kein .alias(). Benennen Sie eine berechnete Spalte über die Keyword-Form (temp_f=...). pd.col("temp").alias("x") lässt sich ohne Beschwerde aufbauen, danach scheitert df.select(...) mit AttributeError: 'Series' object has no attribute 'alias'.
  • Ein Ausdruck, der sich auf einen Skalar reduziert, etwa pd.col("temp").mean(), muss als Keyword übergeben werden (mean_temp=pd.col("temp").mean()); er wird dann auf jede Zeile gebroadcastet. Positional übergeben wirft er TypeError.
  • Eine fehlende Spalte wirft KeyError, genau wie df[["nope"]].

filter(cond=) behält Zeilen über eine boolesche Maske (getestet)

DataFrame.filter wählte bisher nur Labels aus (items=, like=, regex=). In 3.1 nimmt es auch eine Maske:

df.filter(cond=df["temp"] > 17)          # a boolean Series
df.filter(pd.col("temp") > 17)           # an expression, positional is fine
df.filter(lambda d: d["rain"] < 20)      # a callable

Verkettet liest sich das wie Polars, bleibt aber ein pandas-DataFrame:

(
    df.filter(pd.col("rain") < 20)
      .select("city", "temp")
      .sort_values("temp")
)

Fehlende Werte in der Maske zählen standardmäßig als False; übergeben Sie na=True, um sie zu behalten, oder na="raise", um einen Fehler auszulösen.

Die Falle: Eine einfache Liste von Booleans, positional übergeben, geht weiterhin den Label-Pfad. In unserem Test lieferte df.filter([True, False, True]) einen DataFrame mit null Spalten und eine UserWarning, die uns auf cond= hinwies. Schreiben Sie immer cond=, wenn die Maske eine Liste oder ein Array ist.

Polars und pandas 3.1 im Vergleich

AufgabePolarspandas 3.1
Spalten auswählendf.select("a", "b")df.select("a", "b")
Spalte berechnendf.select(pl.col("a") * 2)df.select(pd.col("a") * 2)
Benennen(pl.col("a") * 2).alias("a2")df.select(a2=pd.col("a") * 2)
Zeilen filterndf.filter(pl.col("a") > 1)df.filter(pd.col("a") > 1)
Aggregierendf.select(pl.col("a").mean()) → 1 Zeiledf.select(m=pd.col("a").mean()) → auf jede Zeile gebroadcastet

pandas wird nicht zu Polars: Hinter select steckt keine Lazy Evaluation und kein Query-Optimizer. Es ist Syntax, die Ketten lesbar macht und Ihnen erspart, den DataFrame-Namen zu wiederholen. Wenn Sie einen Engine-Wechsel abwägen, behandelt Polars vs. pandas diese Entscheidung.

Schritt 4: Das schnellere read_csv bekommen und wissen, was es abschaltet

Der Benchmark (getestet)

Eine Datei: 3.000.000 Zeilen × 3 Spalten (float, int, string), 72,5 MB, unkomprimiert, auf lokaler SSD. Bester von drei Durchläufen.

ReaderZeitvs. pandas 3.0.1
pandas 3.0.1, engine="c"0,233 s1x
pandas 3.1.0, mode.max_threads = 1 (seriell)0,089 s2,6x
pandas 3.1.0, 2 Threads0,049 s4,8x
pandas 3.1.0, 4 Threads0,025 s9,3x
pandas 3.1.0, Standard (6 Threads)0,018 s13x
pandas 3.1.0, engine="pyarrow"0,030 s7,8x

Die serielle Zeile passt zu den Release Notes („zwei- bis dreimal schneller“); die parallelen Zeilen kommen obendrauf. Ihre Datei wird abweichen (mehr String-Spalten parsen langsamer), aber die Form des Ergebnisses ist der Punkt: Der Standard-Reader mit engine="c" ist bei einer einfachen lokalen Datei jetzt schneller als PyArrow.

Die Bedingungen (Doku, durch die Zeiten oben bestätigt)

Der parallele Pfad läuft automatisch, wenn alle diese Bedingungen gelten:

  • filepath_or_buffer ist ein lokaler, unkomprimierter Dateipfad
  • die Standard-C-Engine wird genutzt
  • die Datenzeilen umfassen mindestens 5 MB
  • mode.max_threads ist größer als 1 (Standard: CPU-Anzahl, gedeckelt bei 6, und 1, wenn der Prozess auf eine CPU beschränkt ist)
  • keine Option, die die ganze Datei auf einmal braucht: iterator, chunksize, nrows, usecols, index_col, parse_dates, ein skiprows als Liste oder Callable, mehrzeilige Header oder eine Nicht-UTF-8-Kodierung

Alles andere fällt auf den seriellen Reader zurück, und das Ergebnis ist immer identisch mit einem seriellen Lesevorgang.

Wie das in unserem Test aussah (getestet)

AufrufZeitParallel?
pd.read_csv("big.csv")0,018 sja
pd.read_csv("big.csv", usecols=["a", "c"])0,079 snein
pd.read_csv("big.csv", index_col=0)0,091 snein
pd.read_csv("big.csv", nrows=1_000_000)0,032 snein (seriell, ein Drittel der Datei)
pd.read_csv("big.csv", converters={"b": int})0,255 snein (langsamer als ein einfacher Lesevorgang, aber immer noch schneller als derselbe Aufruf auf 3.0)
pd.read_csv(open("big.csv", "rb"))0,091 snein (File-Handle, kein Pfad)
pd.read_csv(io.StringIO(text))0,131 snein
pd.read_csv("big.csv.gz")0,163 snein (komprimiert)
pd.concat(pd.read_csv("big.csv", chunksize=500_000))0,099 snein
pd.read_csv("big.csv", dtype={...})0,034 sja (explizites dtype ist in Ordnung)
pd.read_csv("big.csv", na_values=["z"])0,025 sja

Zwei praktische Folgen:

  • usecols kann einen Lesevorgang jetzt langsamer machen, nicht schneller. Jahrelang lautete der Rat: „Übergib usecols, um nicht benötigte Spalten zu überspringen.“ Bei einer lokalen Datei ≥ 5 MB in 3.1 war es in unserem Test 4x schneller, alles parallel zu lesen und die Spalten danach zu verwerfen, als usecols zu nutzen. Messen Sie, bevor Sie die alte Gewohnheit beibehalten.
  • Übergeben Sie einen Pfad, kein Handle. pd.read_csv("file.csv") ist parallel; pd.read_csv(open("file.csv")) nicht. Wrapper, die pandas ein offenes File-Objekt statt eines Pfads übergeben, verlieren die Beschleunigung.

In einer bereits parallelen Anwendung drosseln

Wenn pandas in Dask, Ray, einem Multiprocessing-Pool oder einem Web-Worker läuft, der ohnehin alle Kerne nutzt, begrenzen Sie die Threads, damit sie sich nicht in die Quere kommen:

import pandas as pd
 
with pd.option_context("mode.max_threads", 1):
    df = pd.read_csv("large.csv")
 
# or globally
pd.set_option("mode.max_threads", 2)

In Docker und Kubernetes folgt die Obergrenze dem CPU-Kontingent der cgroup (Doku, hier nicht getestet), ein auf eine CPU begrenzter Container liest also seriell, ohne dass Sie etwas tun müssen.

Schritt 5: Die Verhaltensänderungen prüfen, die keinen Fehler werfen

Das sind die Änderungen, die ein Ergebnis am ehesten still verändern. Jede wurde auf 3.0.1 und 3.1.0 reproduziert (getestet).

Timedelta und Datetime aus Zahlen sind jetzt standardmäßig Mikrosekunden

In 3.0 erzeugte pd.to_timedelta([1], unit="s") ein timedelta64[s], und Arithmetik behielt diese Auflösung. Eine Division rundete auf ganze Sekunden:

td = pd.to_timedelta([1], unit="s")
print(td / 3)
# pandas 3.0.1 → TimedeltaIndex(['0 days'], dtype='timedelta64[s]', freq=None)
# pandas 3.1.x → TimedeltaIndex(['0 days 00:00:00.333333'], dtype='timedelta64[us]', freq=None)

3.1 behebt das, indem unabhängig von der unit, mit der Sie konvertieren, Mikrosekunden der Standard sind. Wenn Ihr Code Dtypes vergleicht oder sich auf die Auflösung [s] verlassen hat, nutzen Sie explizit .as_unit("s"). Timestamp und to_datetime mit numerischer Eingabe haben sich auf dieselbe Weise geändert.

Verwandt: Timedelta.total_seconds() berücksichtigt jetzt Nanosekunden. pd.Timedelta(nanoseconds=1500).total_seconds() gibt 1.5e-06 statt 1e-06 zurück.

dtype="category" in read_csv erkennt numerische Kategorien

from io import StringIO
data = "zip\n00501\n00501\n10001"
 
pd.read_csv(StringIO(data), dtype="category")["zip"].cat.categories.tolist()
# pandas 3.0.1 → ['00501', '10001']
# pandas 3.1.0 → [501, 10001]        leading zeros gone

Die C-Engine macht jetzt das, was die PyArrow-Engine schon vorher tat. Für Postleitzahlen, Kontonummern und jede mit Nullen aufgefüllte Kennung lesen Sie die Spalte als str und konvertieren danach:

df = pd.read_csv("file.csv", dtype={"zip": "str"})
df["zip"] = df["zip"].astype("category")

Dinge, die früher still durchliefen und jetzt einen Fehler werfen

  • pd.Timestamp(datetime(2020, 12, 31), hour=5) warf in unserem Test ValueError; in 3.0 wurde hour stillschweigend ignoriert. Übergeben Sie stattdessen alle Komponenten als Keyword.
  • pd.to_timedelta("3:25:00 PM") wirft einen Fehler; 3.0 parste es als drei Stunden und verwarf das PM.
  • DataFrame-Arithmetik und Ordnungsvergleiche mit einer category-Series entlang der Standardachse axis="columns" (zum Beispiel df + cat_series) werfen jetzt TypeError, statt auf den Kategorien zu operieren; Gleichheitsvergleiche bleiben unverändert (Doku, reproduziert).
  • Index.values und Index.array geben schreibgeschützte Arrays zurück, Code, der einen Index darüber verändert hat, scheitert jetzt laut, statt Lookups zu beschädigen (Doku).

Regex auf PyArrow-gestützten Strings (getestet)

Mit installiertem PyArrow matchten \w, \d, \s, \b in .str.replace, .str.count und Verwandten in pandas 3.0 nur ASCII. In 3.1 matchen sie wieder Unicode, konsistent mit Pythons re und pandas 2.x. Mit PyArrow 26.0.1 lieferte pd.Series(["héllo wörld", "naïve 東京"]).str.count(r"\w") auf pandas 3.0.6 [8, 4] und auf 3.1.1 [10, 7]. Wenn Sie nicht-englischen Text verarbeiten und nach dem Umstieg auf 3.0 sinkende Zählwerte gesehen haben, ist das die Lösung. 3.1.1 behebt außerdem, dass \s auf PyArrow-Strings \x0b und \x1c nicht matchte.

Sollten Sie jetzt upgraden?

SituationEmpfehlung
Neues Projekt, Python 3.11+Ja. Mit 3.1 starten und ohne inplace schreiben
Skripte und Notebooks auf 3.0Ja. Einmal mit -W "error:The inplace keyword:DeprecationWarning" (oder pytest -W error::pandas.errors.Pandas4Warning) laufen lassen, die Zeilen beheben und die schnelleren CSV-Lesevorgänge behalten
Bibliothek oder Pipeline, die mit Nullen aufgefüllte IDs über dtype="category" lädtUpgraden, aber zuerst dtype={"id": "str"} ergänzen
Abhängig von FLAML, darts oder ÄhnlichemUpgraden, sobald deren 3.1-Fixes erschienen sind (yfinance hat das schon getan, in 1.8.0), oder bis dahin Pandas4Warning filtern
Noch auf pandas 2.xZuerst die Migration 2 → 3 machen (Copy-on-Write, String-Dtype); 3.1 ist obendrauf klein
Noch auf NumPy 1.xBlockiert. Erst NumPy upgraden

pandas 3.1 in Jupyter nutzen

Im Notebook selbst ändert sich nichts. Zwei Hinweise:

  • -W error ist ein Kommandozeilen-Flag und gilt nicht für einen laufenden Kernel. Setzen Sie warnings.simplefilter("error", pd.errors.Pandas4Warning) in die erste Zelle, während Sie aufräumen, und entfernen Sie es danach.
  • Der parallele CSV-Reader braucht den Free-threaded-Build von Python nicht; er funktioniert auf dem Standard-Interpreter.

Sobald eine große Datei in Sekundenbruchteilen geladen ist, ist der langsame Teil das Anschauen. PyGWalker (opens in a new tab) 0.5.0.1 lief in unserem Test auf pandas 3.1 (pyg.to_html(df) hat einen Frame mit 50.000 Zeilen in 0,23 s gerendert), ein Drag-and-Drop-Durchgang über den frisch geladenen DataFrame ist also ein sinnvoller nächster Schritt, bevor Sie den groupby-Code schreiben.

Fehlerbehebung

ResolutionImpossible / „requires numpy>=2.3.3“ — Sie sind auf Python 3.14 oder 3.15 mit einem alten NumPy-Pin. Upgraden Sie NumPy oder lockern Sie den Pin. Unter Python 3.11–3.13 liegt die Untergrenze bei 2.0.2.

Hunderte Pandas4Warning-Zeilen aus site-packages — eine Abhängigkeit, nicht Ihr Code. Aktualisieren Sie sie; gibt es noch keinen Fix, warnings.filterwarnings("ignore", category=pd.errors.Pandas4Warning) setzen und ein Issue mit dem Traceback eröffnen.

read_csv ist nicht schneller — prüfen Sie die Liste in Schritt 4. Die üblichen Verdächtigen sind usecols, index_col, eine komprimierte Datei oder ein File-Objekt statt eines Pfads. Prüfen Sie außerdem, dass pd.get_option("mode.max_threads") nicht 1 ist (standardmäßig ist es None, was „auto“ bedeutet).

df.filter([...]) hat keine Spalten zurückgegeben — Sie haben eine boolesche Liste positional übergeben. Nutzen Sie df.filter(cond=[...]).

AttributeError: 'Series' object has no attribute 'alias' — pd.col-Ausdrücke haben kein funktionierendes alias; benennen Sie die Spalte über die Keyword-Form von select.

Postleitzahlen haben ihre führenden Nullen verloren — dtype="category" erkennt jetzt Integer. Zuerst als str lesen.

Timedelta-Dtype hat sich von [s] zu [us] geändert — in 3.1 erwartet. Nutzen Sie .as_unit("s"), wenn ein nachgelagertes System Sekunden braucht.

FAQ

Was ist Pandas4Warning und wie behebe ich sie?

Es ist die Deprecation-Warnung, die pandas 3.1 für Verhalten ausgibt, das sich in 4.0 ändert, am häufigsten inplace=True bei drop, rename, reset_index, set_index, sort_values, dropna und drop_duplicates. Weisen Sie stattdessen das Ergebnis zu: df = df.drop(columns=["a"]). Führen Sie python -W "error:The inplace keyword:DeprecationWarning" your_script.py aus (oder pytest -W error::pandas.errors.Pandas4Warning für eine Testsuite), um am ersten verbleibenden Aufruf mit einem Traceback anzuhalten; beheben Sie ihn und führen Sie das Skript erneut aus.

Ist inplace=True in pandas 3.1 entfernt?

Nein. Es funktioniert in 3.1 weiterhin und gibt eine Warnung aus. Die Entfernung ist für pandas 4.0 geplant, und nur für die Methoden, die Daten nie in place verändert haben. fillna, replace, where, mask, clip und interpolate behalten das Schlüsselwort.

Warum ist read_csv schneller, und warum meins nicht?

Die C-Engine ist 2–3x schneller, und große lokale Dateien werden standardmäßig parallel gelesen. Wenn Sie keine Änderung sehen, übergeben Sie wahrscheinlich usecols, index_col, nrows, chunksize, eine komprimierte Datei oder ein offenes File-Objekt. Siehe die Tabelle in Schritt 4.

Ist df.select() dasselbe wie select in Polars?

Die Syntax ist absichtlich ähnlich, aber pandas wertet eager aus und hat keinen Query-Optimizer. Nutzen Sie es für lesbare Ketten, nicht für Performance.

Funktioniert pandas 3.1 mit Python 3.15?

Ja. Wheels werden für CPython 3.11 bis 3.15 veröffentlicht. Unter 3.14 und 3.15 brauchen Sie NumPy 2.3.3 oder neuer. Die Python-Seite dieses Upgrades behandelt unsere Anleitung zum Upgrade auf Python 3.15.

Weiterführende Anleitungen