Skip to content

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

Mis à jour le

pandas 3.1.0 (22 octobre 2026) déprécie inplace=True sur drop, rename, sort_values et huit autres méthodes, ajoute DataFrame.select() avec les expressions pd.col() et filter(cond=), et lit les gros CSV en parallèle. Testé sur macOS : un CSV de 72 Mo passe de 0,23 s à 0,02 s, la liste exacte des Pandas4Warning, les options de read_csv qui désactivent le lecteur parallèle sans prévenir, et le piège NumPy 2.3.3 sous Python 3.14.

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 :

  1. Votre code affiche des Pandas4Warning pour chaque inplace=True sur drop, rename, reset_index, set_index, sort_values, dropna, drop_duplicates et quelques autres. La correction est mécanique : df = df.drop(...) au lieu de df.drop(..., inplace=True). Souvent, l'avertissement vient d'une bibliothèque que vous utilisez, pas de votre code.
  2. pd.read_csv sur 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.
  3. Vous obtenez une API à la Polars : df.select("a", pd.col("b") * 2) et df.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 uv neuf 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

ChangementCe que cela signifie pour vousAction
inplace déprécié sur 11 méthodes (PDEP-8)Chaque appel émet un Pandas4Warning ; le paramètre sera retiré dans pandas 4.0Réassignez le résultat : df = df.drop(...)
read_csv parallèle pour les fichiers locaux non compressés ≥ 5 Mo2 à 3x plus rapide en mono-thread, plus jusqu'à 6 threads par défautRien, 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 PolarsOptionnel ; utile dans les chaînes de méthodes
filter(cond=...) accepte un masque booléendf.filter(pd.col("a") > 1) garde des lignesAttention : 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.1Mettez d'abord NumPy à jour, ou épinglez pandas<3.1
Les entrées numériques passent en microsecondes par défautpd.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ériquesLes codes postaux et identifiants perdent leurs zéros initiauxLisez 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.

É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 :

PythonNumPy minimum
3.11 – 3.132.0.2
3.14 – 3.152.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éthodeinplace en 3.1Correction
drop, rename, rename_axisDépréciédf = df.drop(...)
reset_index, set_indexDépréciédf = df.reset_index()
sort_values, sort_indexDépréciédf = df.sort_values("col")
dropna, drop_duplicatesDépréciédf = df.dropna()
eval, queryDépréciédf = df.query("a > 1")
fillna, replace, where, mask, clip, interpolateConservé (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.py

Pour 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.Pandas4Warning

Pandas4Warning 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 :

  1. Mettez la bibliothèque à jour. Beaucoup ont publié un correctif en quelques jours.
  2. 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)
  1. Épinglez pandas<3.1 dans l'environnement qui exécute la bibliothèque non maintenue. N'épinglez pas pandas 3.0 pour toujours : le mot-clé inplace sera 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ésormaisRemplacement
s.dt.dayofweek, .dayofyear, .daysinmonths.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 floatConvertissez d'abord vers un dtype commun ; cela lèvera une erreur dans une future version
ser.values sur une colonne avec fuseau horaireser.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.10

Les 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, puis df.select(...) échoue avec AttributeError: '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ève TypeError.
  • Une colonne absente lève KeyError, comme df[["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 callable

Enchaî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âchePolarspandas 3.1
Sélectionner des colonnesdf.select("a", "b")df.select("a", "b")
Calculer une colonnedf.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 lignesdf.filter(pl.col("a") > 1)df.filter(pd.col("a") > 1)
Agrégerdf.select(pl.col("a").mean()) → 1 lignedf.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.

LecteurTempsvs pandas 3.0.1
pandas 3.0.1, engine="c"0,233 s1x
pandas 3.1.0, mode.max_threads = 1 (série)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, défaut (6 threads)0,018 s13x
pandas 3.1.0, engine="pyarrow"0,030 s7,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_buffer est 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_threads est 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, un skiprows sous 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é)

AppelTempsParallèle ?
pd.read_csv("big.csv")0,018 soui
pd.read_csv("big.csv", usecols=["a", "c"])0,079 snon
pd.read_csv("big.csv", index_col=0)0,091 snon
pd.read_csv("big.csv", nrows=1_000_000)0,032 snon (série, un tiers du fichier)
pd.read_csv("big.csv", converters={"b": int})0,255 snon (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 snon (descripteur de fichier, pas un chemin)
pd.read_csv(io.StringIO(text))0,131 snon
pd.read_csv("big.csv.gz")0,163 snon (compressé)
pd.concat(pd.read_csv("big.csv", chunksize=500_000))0,099 snon
pd.read_csv("big.csv", dtype={...})0,034 soui (un dtype explicite ne pose pas de problème)
pd.read_csv("big.csv", na_values=["z"])0,025 soui

Deux conséquences pratiques :

  • usecols peut maintenant ralentir une lecture au lieu de l'accélérer. Pendant des années, le conseil était « passez usecols pour 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 que usecols dans 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 gone

Le 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é ValueError dans 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 le PM.
  • L'arithmétique et les comparaisons d'ordre entre un DataFrame et une Series category le long de l'axe par défaut axis="columns" (par exemple df + cat_series) lèvent maintenant TypeError au lieu d'opérer sur les catégories ; l'égalité ne change pas (docs, reproduit).
  • Index.values et Index.array renvoient 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 ?

SituationRecommandation
Nouveau projet, Python 3.11+Oui. Démarrez sur 3.1 et écrivez sans inplace
Scripts et notebooks sur 3.0Oui. 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 similaireMigrez 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.xFaites d'abord la migration 2 → 3 (Copy-on-Write, dtype string) ; 3.1 est un petit pas ensuite
Encore sur NumPy 1.xBloqué. Mettez d'abord NumPy à jour

Utiliser pandas 3.1 dans Jupyter

Rien ne change dans le notebook lui-même. Deux remarques :

  • -W error est une option de ligne de commande et ne s'applique pas à un kernel en cours d'exécution. Mettez warnings.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