La bibliothèque Pandas est la référence pour manipuler des données en Python. Pourtant, beaucoup l'utilisent mal. Voici comment optimiser vos opérations.
POURQUOI LE NETTOYAGE DE DONNÉES PREND-IL TANT DE TEMPS ?
Près de 80% du temps d’un data scientist est consacré au nettoyage et à la préparation des données. Or, Pandas, la bibliothèque Python la plus utilisée pour manipuler des données tabulaires, est souvent mal exploitée. Les développeurs écrivent du code qui ressemble à du Python standard, avec des boucles et des modifications successives du même tableau. Résultat : des avertissements incompréhensibles, une mémoire qui gonfle, et des calculs lents. Pourtant, en adoptant les bonnes pratiques, on peut passer moins de temps sur le nettoyage et plus sur l’analyse ou la modélisation.
TRUC N°1 : LA CHAÎNE DE MÉTHODES POUR ÉVITER LES PIÈGES
Imaginons un tableau de ventes avec des dates invalides, des prix négatifs et des codes produits mal formatés. La méthode naïve consiste à modifier le tableau étape par étape, ce qui déclenche souvent l’avertissement SettingWithCopyWarning. Ce message signifie que Pandas n’est pas sûr de savoir si vous modifiez une copie du tableau ou le tableau original. Le problème ? Impossible de savoir si vos modifications sont appliquées correctement.
Prenons un exemple concret avec un tableau de ventes :
import pandas as pd
import numpy as np
# Données brutes de ventes
data = {
'saledate': ['2026-01-01', '2026-01-02', 'invaliddate', '2026-01-04'],
'itemcode': [' PRODA ', ' PRODB', 'PRODC ', ' PROD_D '],
'price': [100.0, 250.0, -99.0, 150.0],
'quantity': [2, 1, 5, 3]
}
df = pd.DataFrame(data)
# Nettoyage naïf (problématique)
df['saledate'] = pd.todatetime(df['sale_date'], errors='coerce')
df['itemcode'] = df['itemcode'].str.strip()
df['total_revenue'] = df['price'] * df['quantity']
# Filtrage des dates invalides et prix négatifs
df = df[df['sale_date'].notna()]
df = df[df['price'] > 0]
# Renommage des colonnes
df.rename(columns={'itemcode': 'productid'}, inplace=True)
print(df)
Le code fonctionne, mais il est difficile à lire et à déboguer. Et si une erreur survient, impossible de savoir où elle s’est produite. La solution ? La chaîne de méthodes.
En enveloppant les opérations dans des parenthèses et en utilisant des méthodes comme .assign(), .query() et .pipe(), on crée un pipeline clair et linéaire. Voici comment faire :
# Nettoyage optimisé avec chaîne de méthodes
cleaned_df = (
df_raw
.copy() # Crée une copie pour éviter de modifier les données originales
.assign(
saledate=lambda d: pd.todatetime(d['sale_date'], errors='coerce'),
total_revenue=lambda d: d['price'] * d['quantity']
)
.pipe(cleanitemcodes) # Applique une fonction personnalisée
.query("sale_date.notna() and price > 0") # Filtre les lignes valides
.rename(columns={'itemcode': 'productid'}) # Renomme la colonne
)
print(cleaned_df)
Résultat : un code plus lisible, sans avertissements, et facile à déboguer. Chaque étape est isolée, et les données originales restent intactes.
TRUC N°2 : OPTIMISER LA MÉMOIRE ET LA VITESSE AVEC LES CATÉGORIES
Un autre piège courant : les colonnes de texte stockées comme des objets. En Python, un objet est un pointeur vers une chaîne de caractères en mémoire. Pour un grand jeu de données avec des valeurs répétitives (comme des statuts : "EN ATTENTE", "TERMINÉ", etc.), cela consomme énormément de mémoire. Sans compter que les opérations de nettoyage comme .apply() sont lentes, car elles exécutent du code Python ligne par ligne.
Prenons un exemple avec un million de lignes contenant des statuts de commandes :
# Nettoyage naïf (lent et gourmand en mémoire)
df['status'] = df['status'].apply(lambda x: x.strip().upper())
Cette méthode prend 0,12 seconde et utilise 53,64 Mo de mémoire. La solution ? Convertir la colonne en catégorie avant de nettoyer :
# Conversion en catégorie avant nettoyage
df['status'] = df['status'].astype('category')
# Nettoyage vectorisé (rapide et économe en mémoire)
df['status'] = df['status'].cat.rename_categories(lambda x: x.strip().upper())
Résultat : 0,0003 seconde et seulement 0,95 Mo de mémoire. Gain de vitesse : 407 fois plus rapide .
Attention : si une colonne contient beaucoup de valeurs différentes (comme des adresses email), les catégories ne servent à rien. Dans ce cas, utilisez directement les méthodes vectorisées sur les objets :
df['status'].str.strip().str.upper()
Cette méthode s’exécute en C, bien plus rapidement que du code Python.
TRUC N°3 : REMPLACER LES VALEURS MANQUANTES PAR GROUPE SANS BOUCLE
Remplacer une valeur manquante (NaN) par la moyenne globale est une erreur classique. Par exemple, si un produit a un prix manquant, utiliser la moyenne de tous les produits fausse les résultats. La bonne méthode ? Utiliser la moyenne du groupe auquel appartient le produit.
La méthode naïve consiste à boucler sur chaque groupe, calculer la moyenne, filtrer le tableau, remplacer les NaN, puis rassembler les morceaux. C’est lent et compliqué. La solution ? Utiliser .transform() avec groupby().
Prenons un exemple avec 100 000 produits répartis en 100 catégories, dont 10% ont des prix manquants :
# Nettoyage naïf (lent)
df['price'] = df.groupby('category')['price'].apply(lambda x: x.fillna(x.mean())).reset_index(level=0, drop=True)
Cette méthode prend 0,0224 seconde. Voici la version optimisée :
# Nettoyage optimisé avec .transform()
group_means = df.groupby('category')['price'].transform('mean')
df['price'] = df['price'].fillna(group_means)
Résultat : 0,0032 seconde. Gain de vitesse : 7 fois plus rapide .
.transform() permet de calculer des statistiques par groupe et de les appliquer directement aux lignes correspondantes, sans avoir à découper et recoller le tableau. C’est magique :
# Remplir les valeurs manquantes par la dernière valeur valide du groupe
df.groupby('group')['val'].transform('ffill')
Cette méthode est ultra-versatile. On peut l’utiliser pour standardiser des données par groupe, remplir des valeurs manquantes, ou même appliquer des transformations complexes.
EN RÉSUMÉ : TROIS RÈGLES POUR DES PANDAS PLUS PERFORMANTS
Pour résumer, voici les trois astuces à retenir :
- 1. Chaînez les méthodes : Utilisez .assign(), .query() et .pipe() pour créer un pipeline clair et sans effet de bord. Évitez les modifications successives du même tableau.
- 2. Optimisez la mémoire avec les catégories : Convertissez les colonnes de texte répétitives en catégorie avant de nettoyer. Utilisez .cat.rename_categories() pour des opérations vectorisées ultra-rapides.
- 3. Remplacez les NaN par groupe avec .transform() : Oubliez les boucles et les .apply() lents. Utilisez groupby().transform() pour appliquer des calculs par groupe directement sur les lignes concernées.
Ces trois techniques transforment un code lent et fragile en un pipeline robuste, rapide et facile à maintenir. Que vous travailliez sur un petit jeu de données ou sur des millions de lignes, elles vous feront gagner un temps précieux.
ALLER PLUS LOIN : DES PANDAS POUR LA PRODUCTION
Les méthodes présentées ici ne sont pas réservées aux prototypes. Elles sont conçues pour fonctionner en production, même avec des jeux de données énormes. En les adoptant, vous réduisez les risques d’erreurs, améliorez la lisibilité du code, et surtout, vous gagnez un temps fou.
Que ce soit pour préparer des données de machine learning, nettoyer des logs, ou analyser des ventes, ces astuces s’appliquent partout. Le secret ? Penser en termes de pipelines fonctionnels plutôt que de modifications impératives. Votre futur vous remerciera.
- KDnuggets
L'indépendance de CLODCO est votre garantie.
Pour que l'actualité de l'IA reste sans filtre et sans concession, votre soutien est indispensable. Votre contribution est le seul moteur de notre liberté éditoriale.
Soutenir CLODCO


