Mettre à jour pandas 3.1 : corriger le Pandas4Warning d'inplace, utiliser df.select() et pd.col(), lire les CSV plus vite
Mis à jour le

La réponse courte : pandas 3.1.0 est sorti le 22 octobre 2026, et la version corrective 3.1.1 a suivi le 4 novembre. Passez directement à 3.1.1 :
pip install --upgrade "pandas>=3.1"
# or, in a uv project
uv add "pandas>=3.1"Trois choses se produisent après la mise à jour :
- Votre code affiche des
Pandas4Warningpour chaqueinplace=Truesurdrop,rename,reset_index,set_index,sort_values,dropna,drop_duplicateset quelques autres. La correction est mécanique :df = df.drop(...)au lieu dedf.drop(..., inplace=True). Souvent, l'avertissement vient d'une bibliothèque que vous utilisez, pas de votre code. pd.read_csvsur de gros fichiers locaux devient beaucoup plus rapide. Un fichier de 72 Mo est passé de 0,23 s sur pandas 3.0.1 à 0,02 s sur 3.1 dans notre test. Certains arguments courants désactivent l'accélération ; ils sont listés plus bas.- Vous obtenez une API à la Polars :
df.select("a", pd.col("b") * 2)etdf.filter(pd.col("a") > 1).
Si vous êtes encore sur pandas 2.x, le passage à 3.x (Copy-on-Write, le dtype string par défaut) est le plus gros changement, et le guide de migration pandas 3.0 (opens in a new tab) est le point de départ. Ce guide couvre 3.0 → 3.1 et les pièges que nous avons rencontrés.
Ce qui a été testé : chaque élément marqué « testé » a été exécuté le 1er novembre 2026 sur un Apple M4 Max (16 cœurs, macOS) dans un environnement virtuel
uvneuf avec CPython 3.14.2, pandas 3.1.0, NumPy 2.5.4 et PyArrow 26.0.0. Les chiffres de comparaison viennent de pandas 3.0.1 avec NumPy 2.4.2 et sans PyArrow sur la même machine. Le comportement sous Windows, Linux, conda et Docker provient de la documentation officielle et n'a pas été testé ici. Le 4 novembre 2026, chaque affirmation testée a été vérifiée de nouveau sur pandas 3.1.1, avec les mêmes résultats.
Ce qui change dans 3.1 et que vous allez remarquer
| Changement | Ce que cela signifie pour vous | Action |
|---|---|---|
inplace déprécié sur 11 méthodes (PDEP-8) | Chaque appel émet un Pandas4Warning ; le paramètre sera retiré dans pandas 4.0 | Réassignez le résultat : df = df.drop(...) |
read_csv parallèle pour les fichiers locaux non compressés ≥ 5 Mo | 2 à 3x plus rapide en mono-thread, plus jusqu'à 6 threads par défaut | Rien, sauf si vous passez usecols, index_col, nrows ou un descripteur de fichier (voir plus bas) |
DataFrame.select() (accepte les expressions pd.col(), disponibles depuis 3.0) | Sélectionner et calculer des colonnes en un appel, à la Polars | Optionnel ; utile dans les chaînes de méthodes |
filter(cond=...) accepte un masque booléen | df.filter(pd.col("a") > 1) garde des lignes | Attention : une liste positionnelle de booléens sélectionne toujours des labels |
| NumPy ≥ 2.0.2 requis (≥ 2.3.3 sous Python 3.14) | Les environnements NumPy 1.x ne peuvent pas installer 3.1 | Mettez d'abord NumPy à jour, ou épinglez pandas<3.1 |
| Les entrées numériques passent en microsecondes par défaut | pd.to_timedelta([1], unit="s") donne maintenant timedelta64[us], pas [s] | Corrige un bug d'arrondi de 3.0 ; utilisez .as_unit() si vous avez besoin d'une résolution précise |
dtype="category" dans read_csv infère des catégories numériques | Les codes postaux et identifiants perdent leurs zéros initiaux | Lisez d'abord ces colonnes en str |
La liste complète se trouve dans le What's new in 3.1.0 officiel (opens in a new tab). La suite de ce guide parcourt les tâches dans l'ordre : installer, corriger les avertissements, utiliser la nouvelle API, accélérer le chargement des CSV, et vérifier les changements de comportement qui peuvent modifier un résultat sans lever d'erreur.
- Mettre à jour pandas 3.1 : corriger inplace (Pandas4Warning), df.select() et read_csv plus rapide
- Passer à OpenCode 2.0 : migrer votre config v1, vos plugins et vos sessions
- Installer Python 3.15 avec uv : imports paresseux (lazy imports) et compatibilité pandas, PyTorch
- Tutoriel Claude Code Mods : créer, tester et installer votre premier mod, avec 15 exemples de la communauté
- GPT Image 2.5 : guide d'utilisation, Flare ou Sunburst et tarifs API
- Comment utiliser DeepSeek Harness : installation, configuration et premier agent
- Runcell Science : l'alternative open source à Claude Science pour la recherche
- Empêcher un Mac de se mettre en veille : capot fermé, Codex et Claude Code
- OpenClaw vs ZeroClaw vs Pi Agent vs Nanobot : quelle stack d’agents IA choisir en 2026 ?
- Comment Claude Code analyse un notebook Jupyter en Data Science : capacités réelles et limites
- Claude Code routines : triggers, cron jobs et automatisation d’agents IA
- Claude Code Desktop : activer le mode Bypass permissions
- Comment Créer Deux Agents Python avec le Protocole A2A de Google - Tutoriel Étape par Étape
- Top 10 bibliothèques de visualisation de données en Python en pleine croissance en 2025
Étape 1 : installer pandas 3.1
Prérequis (testé)
pandas 3.1.0 publie des wheels pour CPython 3.11 à 3.15 (requires_python >= 3.11) et se trouve sur PyPI et conda-forge. La version minimale de NumPy dépend de votre version de Python :
| Python | NumPy minimum |
|---|---|
| 3.11 – 3.13 | 2.0.2 |
| 3.14 – 3.15 | 2.3.3 |
La page whatsnew ne mentionne que 2.0.2. Sous Python 3.14, les métadonnées de la wheel demandent 2.3.3, et c'est ce que le résolveur applique. Épingler NumPy 1.x échoue net :
× 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.Si une dépendance épingle encore numpy<2, c'est cette dépendance qui bloque la mise à jour, pas pandas. Mettez-la à jour ou gardez pandas<3.1 en attendant.
Mise à jour (testé avec uv)
Installez 3.1.1, pas 3.1.0 : 3.1.1 corrige une régression où read_csv et to_csv traitaient des objets chemin comme le tmpdir de pytest comme des descripteurs de fichier ouverts, et pouvaient lever une erreur ou écrire des fichiers incomplets (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 propose 3.1.1 (vérifié le 4 novembre 2026 ; conda install -c conda-forge "pandas>=3.1"), non testé ici.
Installez aussi PyArrow si ce n'est pas déjà fait. pandas 3 l'utilise pour le dtype string par défaut quand il est présent, et le lecteur CSV engine="pyarrow" en a besoin.
Étape 2 : corriger le Pandas4Warning lié à inplace
Après la mise à jour, un code comme celui-ci :
df.drop(columns=["rain"], inplace=True)affiche :
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.Quelles méthodes sont concernées (testé)
La dépréciation couvre les méthodes où inplace=True n'a jamais modifié les valeurs en place. Pour dropna, sort_values et les autres méthodes qui réordonnent les lignes, c'était toujours une réassignation, et la copie que drop, rename ou set_index évitaient autrefois n'a de toute façon plus lieu avec le Copy-on-Write, arrivé dans pandas 3.0.
| Méthode | inplace en 3.1 | Correction |
|---|---|---|
drop, rename, rename_axis | Déprécié | df = df.drop(...) |
reset_index, set_index | Déprécié | df = df.reset_index() |
sort_values, sort_index | Déprécié | df = df.sort_values("col") |
dropna, drop_duplicates | Déprécié | df = df.dropna() |
eval, query | Déprécié | df = df.query("a > 1") |
fillna, replace, where, mask, clip, interpolate | Conservé (elles peuvent modifier les valeurs en place) | Rien à changer |
Dans notre test, les 11 méthodes dépréciées ont toutes émis un avertissement avec inplace=True ; fillna et replace n'en ont pas émis, conformément à la documentation.
Le remplacement tient en une ligne par appel :
# 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)
)Trouver chaque appel dans votre code (testé)
Transformez l'avertissement en erreur pour une exécution, et la traceback pointe la ligne exacte. python -W n'accepte pas une classe tierce comme pandas.errors.Pandas4Warning : il affiche Invalid -W option ignored: invalid module name: 'pandas.errors' et exécute quand même le script. Filtrez plutôt sur le message :
python -W "error:The inplace keyword:DeprecationWarning" your_script.pyPour transformer chaque Pandas4Warning en erreur, pas seulement ceux liés à inplace :
python -c "import runpy, warnings, pandas as pd; warnings.simplefilter('error', pd.errors.Pandas4Warning); runpy.run_path('your_script.py', run_name='__main__')"Les deux s'arrêtent avec une traceback sur la première ligne inplace. Le filtre sur le message laisse tranquilles les autres avertissements de dépréciation.
Pour une suite de tests, pytest applique ses filtres -W une fois pandas importable, donc le nom de classe y fonctionne :
pytest -W error::pandas.errors.Pandas4WarningPandas4Warning est une sous-classe de PandasDeprecationWarning, donc un filtre sur l'une ou l'autre fonctionne. Un grep fait aussi une bonne partie du travail :
grep -rn "inplace=True" --include="*.py" --include="*.ipynb" .Quand l'avertissement vient d'une bibliothèque, pas de vous
C'est le cas le plus fréquent dans les premières semaines après une sortie. Entre le 22 octobre et le 1er novembre 2026, GitHub a vu apparaître environ 300 issues et pull requests mentionnant Pandas4Warning et environ 3 500 mentionnant « pandas 3.1 », dans des projets comme yfinance (29 appels inplace répartis sur 8 fichiers, yfinance #3009 (opens in a new tab) ; corrigé dans yfinance 1.8.0 le 3 novembre), FLAML, marimo, cuDF, darts et category_encoders.
Vous ne pouvez pas corriger cela depuis votre code. Les options, par ordre de préférence :
- Mettez la bibliothèque à jour. Beaucoup ont publié un correctif en quelques jours.
- Faites taire cette seule classe d'avertissement en attendant que la bibliothèque rattrape son retard, plutôt que tous les avertissements :
import warnings
import pandas as pd
warnings.filterwarnings("ignore", category=pd.errors.Pandas4Warning)- Épinglez
pandas<3.1dans l'environnement qui exécute la bibliothèque non maintenue. N'épinglez pas pandas 3.0 pour toujours : le mot-cléinplacesera retiré en 4.0 et l'avertissement est votre préavis.
Autres dépréciations que vous pouvez rencontrer en 3.1 (testé sauf mention contraire)
| Code qui avertit désormais | Remplacement |
|---|---|
s.dt.dayofweek, .dayofyear, .daysinmonth | s.dt.day_of_week, .day_of_year, .days_in_month |
df.select_dtypes(include="object") sur des colonnes string (avertissait déjà en 3.0 ; 3.1 ajoute exclude="object") | Passez "str" explicitement ; "object" ne signifie plus « texte » dans pandas 3 |
s.fillna("missing") sur une colonne float | Convertissez d'abord vers un dtype commun ; cela lèvera une erreur dans une future version |
ser.values sur une colonne avec fuseau horaire | ser.array, ser.to_numpy(), ou ser.dt.tz_convert(None).to_numpy() pour garder l'ancien tableau UTC |
pd.infer_freq(idx) renvoyant "D" | Renverra un objet offset ; utilisez .freqstr ou définissez future.infer_freq_returns_offset |
read_parquet(engine="fastparquet") (docs) | fastparquet est retiré ; utilisez le moteur PyArrow par défaut |
pd.set_eng_float_format() (docs) | pd.set_option("display.precision", n) |
Étape 3 : utiliser df.select(), pd.col() et filter(cond=)
DataFrame.select() et filter(cond=) constituent la nouvelle API visible de 3.1. pd.col() lui-même est arrivé dans pandas 3.0 pour assign() et .loc ; en 3.1, il devient l'argument naturel des deux nouvelles méthodes. Si vous avez utilisé Polars, ils vous sembleront familiers.
select sélectionne et calcule des colonnes en un appel (testé)
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.10Les arguments suivants peuvent faire référence aux colonnes créées plus tôt dans le même appel, comme avec assign :
df.select(temp_c=pd.col("temp"), temp_f=pd.col("temp_c") * 1.8 + 32)pd.col("temp") est une pandas.api.typing.Expression. Elle accepte les opérateurs et accesseurs que vous utiliseriez sur une Series, y compris .str et .round() :
df.select(pd.col("city").str.upper(), pd.col("temp").round(0))Trois points qui nous ont piégés (testé) :
- Il n'y a pas de
.alias(). Nommez une colonne calculée avec la forme à mot-clé (temp_f=...).pd.col("temp").alias("x")se construit sans broncher, puisdf.select(...)échoue avecAttributeError: 'Series' object has no attribute 'alias'. - Une expression qui se réduit à un scalaire, comme
pd.col("temp").mean(), doit être passée en mot-clé (mean_temp=pd.col("temp").mean()) ; elle est alors diffusée sur chaque ligne. Passée en positionnel, elle lèveTypeError. - Une colonne absente lève
KeyError, commedf[["nope"]].
filter(cond=) garde des lignes selon un masque booléen (testé)
DataFrame.filter ne sélectionnait que des labels (items=, like=, regex=). En 3.1, il accepte aussi un masque :
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 callableEnchaîné, cela se lit comme du Polars tout en restant un DataFrame pandas :
(
df.filter(pd.col("rain") < 20)
.select("city", "temp")
.sort_values("temp")
)Les valeurs manquantes du masque comptent comme False par défaut ; passez na=True pour les garder ou na="raise" pour lever une erreur.
Le piège : une simple liste de booléens passée en positionnel emprunte toujours le chemin des labels. Dans notre test, df.filter([True, False, True]) a renvoyé un DataFrame avec zéro colonne et un UserWarning nous disant d'utiliser cond=. Écrivez toujours cond= quand le masque est une liste ou un tableau.
Polars et pandas 3.1 côte à côte
| Tâche | Polars | pandas 3.1 |
|---|---|---|
| Sélectionner des colonnes | df.select("a", "b") | df.select("a", "b") |
| Calculer une colonne | df.select(pl.col("a") * 2) | df.select(pd.col("a") * 2) |
| La nommer | (pl.col("a") * 2).alias("a2") | df.select(a2=pd.col("a") * 2) |
| Filtrer des lignes | df.filter(pl.col("a") > 1) | df.filter(pd.col("a") > 1) |
| Agréger | df.select(pl.col("a").mean()) → 1 ligne | df.select(m=pd.col("a").mean()) → diffusé sur chaque ligne |
pandas ne devient pas Polars : il n'y a ni évaluation paresseuse ni optimiseur de requêtes derrière select. C'est une syntaxe qui rend les chaînes lisibles et évite de répéter le nom du DataFrame. Si vous hésitez à changer de moteur, Polars vs pandas traite cette décision.
Étape 4 : profiter du read_csv plus rapide, et savoir ce qui le désactive
Le benchmark (testé)
Un fichier : 3 000 000 lignes × 3 colonnes (float, int, string), 72,5 Mo, non compressé, sur SSD local. Meilleur de trois exécutions.
| Lecteur | Temps | vs pandas 3.0.1 |
|---|---|---|
pandas 3.0.1, engine="c" | 0,233 s | 1x |
pandas 3.1.0, mode.max_threads = 1 (série) | 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, défaut (6 threads) | 0,018 s | 13x |
pandas 3.1.0, engine="pyarrow" | 0,030 s | 7,8x |
La ligne en série correspond aux notes de version (« deux à trois fois plus rapide ») ; les lignes parallèles viennent en plus. Votre fichier donnera des chiffres différents (plus de colonnes string se parsent plus lentement), mais la forme du résultat est ce qui compte : le lecteur engine="c" par défaut est maintenant plus rapide que PyArrow pour un simple fichier local.
Les conditions (docs, confirmées par les temps ci-dessus)
Le chemin parallèle s'active automatiquement quand toutes ces conditions sont réunies :
filepath_or_bufferest un chemin de fichier local non compressé- le moteur C par défaut est utilisé
- les lignes de données totalisent au moins 5 Mo
mode.max_threadsest supérieur à 1 (défaut : nombre de CPU, plafonné à 6, et 1 quand le processus est limité à un seul CPU)- aucune option qui exige le fichier entier d'un coup :
iterator,chunksize,nrows,usecols,index_col,parse_dates, unskiprowssous forme de liste ou de callable, des en-têtes multi-lignes, ou un encodage autre qu'UTF-8
Tout le reste retombe sur le lecteur en série, et le résultat est toujours identique à une lecture en série.
Ce que cela a donné dans notre test (testé)
| Appel | Temps | Parallèle ? |
|---|---|---|
pd.read_csv("big.csv") | 0,018 s | oui |
pd.read_csv("big.csv", usecols=["a", "c"]) | 0,079 s | non |
pd.read_csv("big.csv", index_col=0) | 0,091 s | non |
pd.read_csv("big.csv", nrows=1_000_000) | 0,032 s | non (série, un tiers du fichier) |
pd.read_csv("big.csv", converters={"b": int}) | 0,255 s | non (plus lent qu'une lecture simple, mais toujours plus rapide que le même appel sur 3.0) |
pd.read_csv(open("big.csv", "rb")) | 0,091 s | non (descripteur de fichier, pas un chemin) |
pd.read_csv(io.StringIO(text)) | 0,131 s | non |
pd.read_csv("big.csv.gz") | 0,163 s | non (compressé) |
pd.concat(pd.read_csv("big.csv", chunksize=500_000)) | 0,099 s | non |
pd.read_csv("big.csv", dtype={...}) | 0,034 s | oui (un dtype explicite ne pose pas de problème) |
pd.read_csv("big.csv", na_values=["z"]) | 0,025 s | oui |
Deux conséquences pratiques :
usecolspeut maintenant ralentir une lecture au lieu de l'accélérer. Pendant des années, le conseil était « passezusecolspour sauter les colonnes inutiles ». Sur un fichier local ≥ 5 Mo en 3.1, tout lire en parallèle puis supprimer des colonnes a été 4x plus rapide queusecolsdans notre test. Mesurez avant de garder la vieille habitude.- Passez un chemin, pas un descripteur.
pd.read_csv("file.csv")est parallèle ;pd.read_csv(open("file.csv"))ne l'est pas. Les wrappers qui donnent à pandas un objet fichier ouvert au lieu d'un chemin perdent l'accélération.
Réduire le parallélisme dans une application déjà parallèle
Si pandas tourne dans Dask, Ray, un pool multiprocessing ou un worker web qui utilise déjà tous les cœurs, plafonnez les threads pour qu'ils ne se gênent pas :
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)Dans Docker et Kubernetes, le plafond suit le quota CPU du cgroup (docs, non testé ici) : un conteneur limité à un CPU lit donc en série sans que vous ayez rien à faire.
Étape 5 : vérifier les changements de comportement qui ne lèvent pas d'erreur
Ce sont les changements les plus susceptibles de modifier un résultat en silence. Chacun a été reproduit sur 3.0.1 et 3.1.0 (testé).
Les Timedelta et datetime créés à partir de nombres passent en microsecondes par défaut
En 3.0, pd.to_timedelta([1], unit="s") produisait un timedelta64[s], et l'arithmétique conservait cette résolution. Une division arrondissait à la seconde entière :
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 corrige cela en passant par défaut en microsecondes, quelle que soit l'unit de conversion. Si votre code comparait des dtypes ou dépendait d'une résolution [s], utilisez .as_unit("s") explicitement. Timestamp et to_datetime avec une entrée numérique ont changé de la même façon.
Dans le même esprit : Timedelta.total_seconds() inclut maintenant les nanosecondes. pd.Timedelta(nanoseconds=1500).total_seconds() renvoie 1.5e-06 au lieu de 1e-06.
dtype="category" dans read_csv infère des catégories numériques
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 goneLe moteur C fait maintenant ce que le moteur PyArrow faisait déjà. Pour les codes postaux, numéros de compte et tout identifiant complété par des zéros, lisez la colonne en str et convertissez ensuite :
df = pd.read_csv("file.csv", dtype={"zip": "str"})
df["zip"] = df["zip"].astype("category")Ce qui passait en silence et lève maintenant une erreur
pd.Timestamp(datetime(2020, 12, 31), hour=5)a levéValueErrordans notre test ; en 3.0,hourétait ignoré sans bruit. Passez tous les composants par mot-clé.pd.to_timedelta("3:25:00 PM")lève une erreur ; 3.0 l'interprétait comme trois heures et ignorait lePM.- L'arithmétique et les comparaisons d'ordre entre un DataFrame et une Series
categoryle long de l'axe par défautaxis="columns"(par exempledf + cat_series) lèvent maintenantTypeErrorau lieu d'opérer sur les catégories ; l'égalité ne change pas (docs, reproduit). Index.valuesetIndex.arrayrenvoient des tableaux en lecture seule : le code qui modifiait un index à travers eux échoue maintenant clairement au lieu de corrompre les recherches (docs).
Regex sur les strings PyArrow (testé)
Avec PyArrow installé, \w, \d, \s, \b dans .str.replace, .str.count et consorts ne correspondaient qu'à l'ASCII dans pandas 3.0. En 3.1, ils correspondent de nouveau à l'Unicode, comme le re de Python et pandas 2.x. Avec PyArrow 26.0.1, pd.Series(["héllo wörld", "naïve 東京"]).str.count(r"\w") a renvoyé [8, 4] sur pandas 3.0.6 et [10, 7] sur 3.1.1. Si vous traitez du texte non anglais et avez vu des comptages chuter en passant à 3.0, voilà le correctif. 3.1.1 corrige aussi \s qui ne correspondait pas à \x0b et \x1c sur les strings PyArrow.
Faut-il migrer maintenant ?
| Situation | Recommandation |
|---|---|
| Nouveau projet, Python 3.11+ | Oui. Démarrez sur 3.1 et écrivez sans inplace |
| Scripts et notebooks sur 3.0 | Oui. Lancez une fois avec -W "error:The inplace keyword:DeprecationWarning" (ou pytest -W error::pandas.errors.Pandas4Warning), corrigez les lignes et gardez les lectures CSV plus rapides |
Bibliothèque ou pipeline qui charge des identifiants à zéros initiaux avec dtype="category" | Migrez, mais ajoutez d'abord dtype={"id": "str"} |
| Dépend de FLAML, darts ou similaire | Migrez quand ils publient leurs correctifs 3.1 (yfinance l'a déjà fait, dans 1.8.0), ou filtrez Pandas4Warning en attendant |
| Encore sur pandas 2.x | Faites d'abord la migration 2 → 3 (Copy-on-Write, dtype string) ; 3.1 est un petit pas ensuite |
| Encore sur NumPy 1.x | Bloqué. Mettez d'abord NumPy à jour |
Utiliser pandas 3.1 dans Jupyter
Rien ne change dans le notebook lui-même. Deux remarques :
-W errorest une option de ligne de commande et ne s'applique pas à un kernel en cours d'exécution. Mettezwarnings.simplefilter("error", pd.errors.Pandas4Warning)dans la première cellule pendant le nettoyage, puis retirez-la.- Le lecteur CSV parallèle n'a pas besoin du build free-threaded de Python ; il fonctionne sur l'interpréteur standard.
Une fois qu'un gros fichier se charge en une fraction de seconde, la partie lente, c'est de le regarder. PyGWalker (opens in a new tab) 0.5.0.1 a fonctionné sur pandas 3.1 dans notre test (pyg.to_html(df) a rendu un DataFrame de 50 000 lignes en 0,23 s), donc un passage en glisser-déposer sur le DataFrame fraîchement chargé est une étape raisonnable avant d'écrire le code groupby.
Dépannage
ResolutionImpossible / « requires numpy>=2.3.3 » — vous êtes sous Python 3.14 ou 3.15 avec un ancien épinglage de NumPy. Mettez NumPy à jour ou assouplissez l'épinglage. Sous Python 3.11–3.13, le minimum est 2.0.2.
Des centaines de lignes Pandas4Warning venant de site-packages — une dépendance, pas votre code. Mettez-la à jour ; si aucun correctif n'existe encore, warnings.filterwarnings("ignore", category=pd.errors.Pandas4Warning) et ouvrez une issue avec la traceback.
read_csv n'est pas plus rapide — vérifiez la liste de l'étape 4. Les coupables habituels sont usecols, index_col, un fichier compressé, ou un objet fichier au lieu d'un chemin. Vérifiez aussi que pd.get_option("mode.max_threads") n'est pas 1 (il vaut None par défaut, ce qui signifie « auto »).
df.filter([...]) n'a renvoyé aucune colonne — vous avez passé une liste de booléens en positionnel. Utilisez df.filter(cond=[...]).
AttributeError: 'Series' object has no attribute 'alias' — les expressions pd.col n'ont pas d'alias qui fonctionne ; nommez la colonne avec la forme à mot-clé de select.
Les codes postaux ont perdu leurs zéros initiaux — dtype="category" infère maintenant des entiers. Lisez d'abord en str.
Le dtype Timedelta est passé de [s] à [us] — c'est attendu en 3.1. Utilisez .as_unit("s") si un système en aval a besoin de secondes.
FAQ
Qu'est-ce que Pandas4Warning et comment le corriger ?
C'est l'avertissement de dépréciation que pandas 3.1 émet pour les comportements qui changent en 4.0, le plus souvent inplace=True sur drop, rename, reset_index, set_index, sort_values, dropna et drop_duplicates. Réassignez le résultat à la place : df = df.drop(columns=["a"]). Lancez python -W "error:The inplace keyword:DeprecationWarning" your_script.py (ou pytest -W error::pandas.errors.Pandas4Warning pour une suite de tests) pour vous arrêter avec une traceback au premier appel restant ; corrigez-le puis relancez.
inplace=True est-il supprimé dans pandas 3.1 ?
Non. Il fonctionne encore en 3.1 et affiche un avertissement. La suppression est prévue pour pandas 4.0, et seulement pour les méthodes qui n'ont jamais modifié les données en place. fillna, replace, where, mask, clip et interpolate conservent le mot-clé.
Pourquoi read_csv est-il plus rapide, et pourquoi pas le mien ?
Le moteur C est 2 à 3x plus rapide et les gros fichiers locaux sont lus en parallèle par défaut. Si vous ne voyez aucun changement, vous passez probablement usecols, index_col, nrows, chunksize, un fichier compressé ou un objet fichier ouvert. Voir le tableau de l'étape 4.
df.select() est-il identique au select de Polars ?
La syntaxe est volontairement proche, mais pandas évalue immédiatement et n'a pas d'optimiseur de requêtes. Utilisez-le pour des chaînes lisibles, pas pour la performance.
pandas 3.1 fonctionne-t-il avec Python 3.15 ?
Oui. Des wheels sont publiées pour CPython 3.11 à 3.15. Sous 3.14 et 3.15, il vous faut NumPy 2.3.3 ou plus récent. Pour le volet Python de cette mise à jour, voir notre guide de mise à jour vers Python 3.15.
Guides associés
- Tutoriel Pandas read_csv() : importer des fichiers CSV
- Comment supprimer une colonne dans pandas
- Filtrer les lignes d'un DataFrame pandas
- Renommer une colonne dans pandas
- Polars vs pandas
- Guide de mise à jour vers Python 3.15
- Comment mettre à jour les paquets Python