
7 astuces de performances Pandas que tout data scientist devrait connaître
un article dans lequel j’ai parcouru certains des outils DataFrame les plus récents en Python, tels que Polars et DuckDB.
J’ai exploré comment ils peuvent améliorer le flux de travail de la science des données et fonctionner plus efficacement lors de la gestion de grands ensembles de données.
Voici un lien vers l’article.
L’idée générale était de donner aux professionnels des données une idée de ce à quoi ressemblent les « dataframes modernes » et de la manière dont ces outils pourraient remodeler la façon dont nous travaillons avec les données.
Mais quelque chose d’intéressant s’est produit : grâce aux retours que j’ai reçus, j’ai réalisé que de nombreux data scientists s’appuient encore fortement sur Pandas pour la plupart de leur travail quotidien.
Et je comprends parfaitement pourquoi.
Même avec toutes les nouvelles options disponibles, les Pandas restent l’épine dorsale de la science des données Python.
Et cela ne repose même pas sur quelques commentaires.
Un récent État de la science des données une enquête rapporte que 77% des praticiens utilisez Pandas pour l’exploration et le traitement des données.
J’aime considérer les Pandas comme ce vieil ami fiable que vous n’arrêtez pas d’appeler : peut-être pas le plus tape-à-l’œil, mais vous savez qu’il fait toujours le travail.
Ainsi, même si les outils les plus récents ont absolument leurs points forts, il est clair que Pandas ne va nulle part de si tôt.
Et pour beaucoup d’entre nous, le véritable défi n’est pas de remplacer Pandas, mais de le rendre plus efficace et un peu moins pénible lorsque nous travaillons avec des ensembles de données plus volumineux.
Dans cet article, je vais vous présenter sept façons pratiques d’accélérer vos flux de travail Pandas. Ceux-ci sont simples à mettre en œuvre mais capables de rendre votre code sensiblement plus rapide.
Configuration et conditions préalables
Avant de nous lancer, voici ce dont vous aurez besoin. J’utilise Python 3.10+ et Pandas 2.x dans ce tutoriel. Si vous utilisez une ancienne version, vous pouvez simplement la mettre à jour rapidement :
pip install --upgrade pandas
C’est vraiment tout ce dont vous avez besoin. Un environnement standard, tel que Jupyter Notebook, VS Code ou Google Colab, fonctionne très bien.
Si NumPy est déjà installé, comme la plupart des gens, tout le reste de ce didacticiel devrait fonctionner sans aucune configuration supplémentaire.
1. Accélérez read_csv Avec des paramètres par défaut plus intelligents
Je me souviens de la première fois que j’ai travaillé avec un fichier CSV de 2 Go.
Les ventilateurs de mon ordinateur portable hurlaient, l’ordinateur portable ne cessait de geler et je regardais la barre de progression, me demandant si elle finirait un jour.
J’ai réalisé plus tard que le ralentissement n’était pas dû à Pandas lui-même, mais plutôt parce que je le laissais tout détecter automatiquement et charger les 30 colonnes alors que j’en avais seulement besoin de 6.
Une fois que j’ai commencé à spécifier les types de données et à sélectionner uniquement ce dont j’avais besoin, les choses sont devenues sensiblement plus rapides.
Les tâches qui me faisaient normalement regarder une barre de progression figée se déroulaient désormais sans problème et j’avais enfin l’impression que mon ordinateur portable était de mon côté.
Laissez-moi vous montrer exactement comment je le fais.
Spécifiez les types à l’avance
Lorsque vous forcez Pandas à deviner les types de données, il doit analyser l’intégralité du fichier. Si vous savez déjà quelles doivent être vos colonnes, dites-lui simplement directement :
df = pd.read_csv(
"sales_data.csv",
dtype={
"store_id": "int32",
"product_id": "int32",
"category": "category"
}
)
Chargez uniquement les colonnes dont vous avez besoin
Parfois, votre CSV comporte des dizaines de colonnes, mais vous ne vous souciez que de quelques-unes. Charger le reste ne fait que gaspiller de la mémoire et ralentir le processus.
cols_to_use = ["order_id", "customer_id", "price", "quantity"]
df = pd.read_csv("orders.csv", usecols=cols_to_use)
Utiliser chunksize pour les fichiers volumineux
Pour les fichiers très volumineux qui ne tiennent pas en mémoire, la lecture par morceaux vous permet de traiter les données en toute sécurité sans faire planter votre ordinateur portable.
chunks = pd.read_csv("logs.csv", chunksize=50_000)
for chunk in chunks:
# process each chunk as needed
pass
Simple, pratique et ça marche vraiment.
Une fois vos données chargées efficacement, la prochaine chose qui vous ralentira est la façon dont Pandas les stocke en mémoire.
Même si vous n’avez chargé que les colonnes dont vous avez besoin, l’utilisation de types de données inefficaces peut ralentir silencieusement vos flux de travail et consommer de la mémoire.
C’est pourquoi l’astuce suivante consiste à choisir les bons types de données pour rendre vos opérations Pandas plus rapides et plus légères.
2. Utilisez les bons types de données pour réduire la mémoire et accélérer les opérations
L’un des moyens les plus simples d’accélérer vos flux de travail Pandas consiste à stocker les données dans le bon type.
Beaucoup de gens s’en tiennent à la valeur par défaut object ou float64 genres. Ils sont flexibles, mais croyez-moi, ils sont lourds.
Le passage à des types plus petits ou plus adaptés peut réduire l’utilisation de la mémoire et améliorer sensiblement les performances.
Convertir des entiers et des flottants en types plus petits
Si une colonne n’a pas besoin d’une précision de 64 bits, la conversion descendante peut économiser de la mémoire :
# Example dataframe
df = pd.DataFrame({
"user_id": [1, 2, 3, 4],
"score": [99.5, 85.0, 72.0, 100.0]
})
# Downcast integer and float columns
df["user_id"] = df["user_id"].astype("int32")
df["score"] = df["score"].astype("float32")
Utiliser category pour les chaînes répétées
Les colonnes de chaînes contenant de nombreuses valeurs répétées, comme les noms de pays ou les catégories de produits, bénéficient énormément d’une conversion en category taper:
df["country"] = df["country"].astype("category")
df["product_type"] = df["product_type"].astype("category")
Cela économise de la mémoire et rend les opérations telles que le filtrage et le regroupement sensiblement plus rapides.
Vérifiez l’utilisation de la mémoire avant et après
Vous pouvez voir l’effet immédiatement :
print(df.info(memory_usage="deep"))
J’ai vu l’utilisation de la mémoire chuter de 50 % ou plus sur de grands ensembles de données. Et lorsque vous utilisez moins de mémoire, les opérations telles que le filtrage et les jointures s’exécutent plus rapidement car les Pandas ont moins de données à mélanger.
3. Arrêtez la boucle. Commencer la vectorisation
L’une des plus grosses erreurs de performances que je constate est l’utilisation de boucles Python ou .apply() pour les opérations pouvant être vectorisées.
Les boucles sont faciles à écrire, mais Pandas est construit autour d’opérations vectorisées qui s’exécutent en C sous le capot, et elles s’exécutent beaucoup plus rapidement.
Approche lente utilisant .apply() (ou une boucle) :
# Example: adding 10% tax to prices
df["price_with_tax"] = df["price"].apply(lambda x: x * 1.1)
Cela fonctionne bien sur de petits ensembles de données, mais une fois que vous avez atteint des centaines de milliers de lignes, l’exploration commence.
Approche vectorisée rapide :
# Vectorized operation
df["price_with_tax"] = df["price"] * 1.1
C’est ça. Même résultat, des ordres de grandeur plus rapides.
4. Utiliser loc et iloc la bonne façon
Une fois, j’ai essayé de filtrer un grand ensemble de données avec quelque chose comme df[df["price"] > 100]["category"]. Non seulement les Pandas m’ont lancé des avertissements, mais le code était plus lent qu’il n’aurait dû l’être.
J’ai appris assez rapidement que l’indexation chaînée est compliquée et inefficace ; cela pourrait également entraîner des bugs subtils et des problèmes de performances.
En utilisant loc et iloc correctement rend votre code plus rapide et plus facile à lire.
Utiliser loc pour l’indexation basée sur les étiquettes
Lorsque vous souhaitez filtrer les lignes et sélectionner les colonnes par nom, loc est votre meilleur pari :
# Select rows where price > 100 and only the 'category' column
filtered = df.loc[df["price"] > 100, "category"]
C’est plus sûr et plus rapide que le chaînage, et cela évite le fameux SettingWithCopyWarning.
Utiliser iloc pour l’indexation basée sur la position
Si vous préférez travailler avec des positions de lignes et de colonnes :
# Select first 5 rows and the first 2 columns
subset = df.iloc[:5, :2]
L’utilisation de ces méthodes permet de conserver votre code propre et efficace, en particulier lorsque vous effectuez des affectations ou un filtrage complexe.
5. Utiliser query() pour un filtrage plus rapide et plus propre
Lorsque votre logique de filtrage commence à devenir compliquée, query() peut rendre les choses beaucoup plus gérables.
Au lieu d’empiler plusieurs conditions booléennes entre parenthèses, query() vous permet d’écrire des filtres dans une syntaxe plus propre, presque proche de celle de SQL.
Et dans de nombreux cas, cela s’exécute plus rapidement car Pandas peut optimiser l’expression en interne.
# More readable filtering using query()
high_value = df.query("price > 100 and quantity < 50")
Cela s’avère particulièrement pratique lorsque vos conditions commencent à s’empiler ou lorsque vous souhaitez que votre code paraisse suffisamment propre pour pouvoir le revoir une semaine plus tard sans vous demander à quoi vous pensiez.
Il s’agit d’une simple mise à niveau qui rend votre code plus intentionnel et plus facile à maintenir.
6. Convertir les chaînes répétitives en catégories
Si votre colonne est remplie de valeurs de texte répétées, telles que des catégories de produits ou des noms d’emplacement, la convertir en type catégoriel peut vous donner une amélioration immédiate des performances.
J’en ai fait l’expérience personnellement.
Pandas stocke les données catégorielles de manière beaucoup plus compacte en remplaçant chaque valeur unique par un code numérique interne.
Cela permet de réduire l’utilisation de la mémoire et d’accélérer les opérations sur cette colonne.
# Converting a string column to a categorical type
df["category"] = df["category"].astype("category")
Les catégories ne feront pas grand-chose pour un texte désordonné et de forme libre, mais pour les étiquettes structurées qui se répètent sur plusieurs lignes, elles constituent l’une des optimisations les plus simples et les plus efficaces que vous puissiez réaliser.
7. Chargez des fichiers volumineux en morceaux plutôt que d’un seul coup
L’un des moyens les plus rapides de surcharger votre système est d’essayer de charger un fichier CSV volumineux en une seule fois.
Les pandas essaieront de tout mettre en mémoire, ce qui peut ralentir considérablement les choses ou faire planter complètement votre session.
La solution consiste à charger le fichier en morceaux gérables et à traiter chacun d’eux au fur et à mesure de son arrivée. Cette approche maintient votre utilisation de la mémoire stable tout en vous permettant de travailler sur l’intégralité de l’ensemble de données.
# Process a large CSV file in chunks
chunks = []
for chunk in pd.read_csv("large_data.csv", chunksize=100_000):
chunk["total"] = chunk["price"] * chunk["quantity"]
chunks.append(chunk)
df = pd.concat(chunks, ignore_index=True)
La segmentation est particulièrement utile lorsque vous traitez des journaux, des enregistrements de transactions ou des exportations brutes bien plus volumineuses que ce qu’un ordinateur portable normal peut gérer confortablement.
J’ai appris cela à mes dépens lorsque j’ai essayé une fois de charger un CSV de plusieurs gigaoctets en une seule fois, et tout mon système a répondu comme s’il avait besoin d’un moment pour réfléchir à ses choix de vie.
Après cette expérience, le chunking est devenu mon approche privilégiée.
Au lieu d’essayer de tout charger en même temps, vous prenez une pièce gérable, la traitez, enregistrez le résultat, puis passez à la pièce suivante.
La finale concat Cette étape vous donne un ensemble de données propre et entièrement traité sans exercer de pression inutile sur votre machine.
Cela semble presque trop simple, mais une fois que vous aurez constaté à quel point le flux de travail devient fluide, vous vous demanderez pourquoi vous n’avez pas commencé à l’utiliser beaucoup plus tôt.
Pensées finales
Travailler avec Pandas devient beaucoup plus facile une fois que vous commencez à utiliser les fonctionnalités conçues pour rendre votre flux de travail plus rapide et plus efficace.
Les techniques décrites dans cet article ne sont pas compliquées, mais elles font une différence notable lorsque vous les appliquez de manière cohérente.
Ces améliorations peuvent sembler minimes individuellement, mais ensemble, elles peuvent transformer la rapidité avec laquelle vous passez des données brutes à des informations significatives.
Si vous développez de bonnes habitudes autour de la façon dont vous écrivez et structurez votre code Pandas, les performances deviennent beaucoup moins problématiques.
De petites optimisations s’additionnent et, au fil du temps, elles rendent l’ensemble de votre flux de travail plus fluide et plus délibéré.



