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

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:
- Ihr Code gibt
Pandas4Warningaus, und zwar für jedesinplace=Truebeidrop,rename,reset_index,set_index,sort_values,dropna,drop_duplicatesund einigen weiteren Methoden. Die Lösung ist mechanisch:df = df.drop(...)stattdf.drop(..., inplace=True). Oft kommt die Warnung aus einer Bibliothek, die Sie nutzen, nicht aus Ihrem eigenen Code. pd.read_csvwird 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.- Sie bekommen eine API im Polars-Stil:
df.select("a", pd.col("b") * 2)unddf.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
| Änderung | Was das für Sie bedeutet | Aktion |
|---|---|---|
inplace deprecated bei 11 Methoden (PDEP-8) | Jeder Aufruf gibt eine Pandas4Warning aus; in pandas 4.0 wird der Parameter entfernt | Ergebnis zuweisen: df = df.drop(...) |
Paralleles read_csv für lokale, unkomprimierte Dateien ≥ 5 MB | 2–3x schneller im Single-Thread, dazu standardmäßig bis zu 6 Threads | Nichts, 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-Stil | Optional; nützlich in Methodenketten |
filter(cond=...) akzeptiert eine boolesche Maske | df.filter(pd.col("a") > 1) behält Zeilen | Achtung: 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 installieren | Erst NumPy upgraden oder pandas<3.1 pinnen |
| Numerische Eingaben werden standardmäßig Mikrosekunden | pd.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 Kategorien | Postleitzahlen und IDs verlieren führende Nullen | Diese 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.
- pandas 3.1 Upgrade: Pandas4Warning beheben, df.select() nutzen, read_csv beschleunigen
- OpenCode 2.0 Upgrade: v1-Konfiguration, Plugins und Sessions migrieren
- Python 3.15 installieren und upgraden: uv, Lazy Imports und Paket-Kompatibilität getestet
- Claude Code Mods Tutorial: Eigenen Mod erstellen, testen und installieren, plus 15 Community-Beispiele
- GPT Image 2.5 nutzen: Flare vs. Sunburst, Anleitung und API-Preise
- DeepSeek Harness nutzen: Installation, Einrichtung und der erste Agent-Lauf
- Runcell Science: Open-Source-Alternative zu Claude Science für Forschungsteams
- Mac Ruhezustand verhindern: Codex, Claude Code und KI-Agenten weiterlaufen lassen
- OpenClaw vs ZeroClaw vs Pi Agent vs Nanobot: Welchen KI-Agenten-Stack sollten Sie 2026 wählen?
- Wie Claude Code Jupyter Notebooks analysiert: Data Science, Grenzen und die bessere Alternative
- Claude Code Routines: KI-Cronjobs für Agenten
- Claude Code Desktop: Bypass permissions aktivieren
- Schritt-für-Schritt-Anleitung zur Erstellung von zwei Python-Agenten mit Googles A2A-Protokoll
- Die Top 10 wachsenden Data Visualization Libraries in Python im Jahr 2025
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:
| Python | Minimales NumPy |
|---|---|
| 3.11 – 3.13 | 2.0.2 |
| 3.14 – 3.15 | 2.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.
| Methode | inplace in 3.1 | Lösung |
|---|---|---|
drop, rename, rename_axis | Deprecated | df = df.drop(...) |
reset_index, set_index | Deprecated | df = df.reset_index() |
sort_values, sort_index | Deprecated | df = df.sort_values("col") |
dropna, drop_duplicates | Deprecated | df = df.dropna() |
eval, query | Deprecated | df = df.query("a > 1") |
fillna, replace, where, mask, clip, interpolate | Bleibt (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.pyUm 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.Pandas4WarningPandas4Warning 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:
- Die Bibliothek aktualisieren. Viele haben innerhalb weniger Tage Fixes veröffentlicht.
- 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)pandas<3.1pinnen in der Umgebung, in der die ungepflegte Bibliothek läuft. Pinnen Sie pandas 3.0 aber nicht für immer; dasinplace-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 warnt | Ersatz |
|---|---|
s.dt.dayofweek, .dayofyear, .daysinmonth | s.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-Spalte | Zuerst in einen gemeinsamen Dtype casten; das wird in einer künftigen Version einen Fehler werfen |
ser.values auf einer Spalte mit Zeitzone | ser.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ück | Wird 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.10Spä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 scheitertdf.select(...)mitAttributeError: '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 erTypeError. - Eine fehlende Spalte wirft
KeyError, genau wiedf[["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 callableVerkettet 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
| Aufgabe | Polars | pandas 3.1 |
|---|---|---|
| Spalten auswählen | df.select("a", "b") | df.select("a", "b") |
| Spalte berechnen | df.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 filtern | df.filter(pl.col("a") > 1) | df.filter(pd.col("a") > 1) |
| Aggregieren | df.select(pl.col("a").mean()) → 1 Zeile | df.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.
| Reader | Zeit | vs. pandas 3.0.1 |
|---|---|---|
pandas 3.0.1, engine="c" | 0,233 s | 1x |
pandas 3.1.0, mode.max_threads = 1 (seriell) | 0,089 s | 2,6x |
| pandas 3.1.0, 2 Threads | 0,049 s | 4,8x |
| pandas 3.1.0, 4 Threads | 0,025 s | 9,3x |
| pandas 3.1.0, Standard (6 Threads) | 0,018 s | 13x |
pandas 3.1.0, engine="pyarrow" | 0,030 s | 7,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_bufferist ein lokaler, unkomprimierter Dateipfad- die Standard-C-Engine wird genutzt
- die Datenzeilen umfassen mindestens 5 MB
mode.max_threadsist 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, einskiprowsals 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)
| Aufruf | Zeit | Parallel? |
|---|---|---|
pd.read_csv("big.csv") | 0,018 s | ja |
pd.read_csv("big.csv", usecols=["a", "c"]) | 0,079 s | nein |
pd.read_csv("big.csv", index_col=0) | 0,091 s | nein |
pd.read_csv("big.csv", nrows=1_000_000) | 0,032 s | nein (seriell, ein Drittel der Datei) |
pd.read_csv("big.csv", converters={"b": int}) | 0,255 s | nein (langsamer als ein einfacher Lesevorgang, aber immer noch schneller als derselbe Aufruf auf 3.0) |
pd.read_csv(open("big.csv", "rb")) | 0,091 s | nein (File-Handle, kein Pfad) |
pd.read_csv(io.StringIO(text)) | 0,131 s | nein |
pd.read_csv("big.csv.gz") | 0,163 s | nein (komprimiert) |
pd.concat(pd.read_csv("big.csv", chunksize=500_000)) | 0,099 s | nein |
pd.read_csv("big.csv", dtype={...}) | 0,034 s | ja (explizites dtype ist in Ordnung) |
pd.read_csv("big.csv", na_values=["z"]) | 0,025 s | ja |
Zwei praktische Folgen:
usecolskann einen Lesevorgang jetzt langsamer machen, nicht schneller. Jahrelang lautete der Rat: „Übergibusecols, 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, alsusecolszu 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 goneDie 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 TestValueError; in 3.0 wurdehourstillschweigend 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 dasPM.- DataFrame-Arithmetik und Ordnungsvergleiche mit einer
category-Series entlang der Standardachseaxis="columns"(zum Beispieldf + cat_series) werfen jetztTypeError, statt auf den Kategorien zu operieren; Gleichheitsvergleiche bleiben unverändert (Doku, reproduziert). Index.valuesundIndex.arraygeben 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?
| Situation | Empfehlung |
|---|---|
| Neues Projekt, Python 3.11+ | Ja. Mit 3.1 starten und ohne inplace schreiben |
| Skripte und Notebooks auf 3.0 | Ja. 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ädt | Upgraden, aber zuerst dtype={"id": "str"} ergänzen |
| Abhängig von FLAML, darts oder Ähnlichem | Upgraden, 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.x | Zuerst die Migration 2 → 3 machen (Copy-on-Write, String-Dtype); 3.1 ist obendrauf klein |
| Noch auf NumPy 1.x | Blockiert. Erst NumPy upgraden |
pandas 3.1 in Jupyter nutzen
Im Notebook selbst ändert sich nichts. Zwei Hinweise:
-W errorist ein Kommandozeilen-Flag und gilt nicht für einen laufenden Kernel. Setzen Siewarnings.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
- Pandas read_csv: Die vollständige Anleitung zu pd.read_csv()
- Spalten in Pandas entfernen
- Zeilen in Pandas filtern
- Spalten in Pandas umbenennen
- Polars vs. pandas
- Python 3.15 installieren und upgraden
- Python-Pakete aktualisieren