Pandas Data Cleaning : workflow pratique
Updated on
Des données sales bloquent l’analyse très tôt. Des fillna ou remplacements ponctuels masquent des problèmes réels : mauvais types, doublons silencieux ou outliers qui biaisent les métriques.
Cadre PAS :
- Problème : Types mixtes, valeurs manquantes et doublons cassent les joins et faussent les stats.
- Agiter : Les correctifs ponctuels cachent les soucis jusqu’à la fin du projet et génèrent du rework.
- Solution : Un checklist réutilisable : standardiser les types, traiter les nuls intentionnellement, gérer les outliers, dédupliquer et valider avant export.
Workflow en bref
| Étape | Action | Exemple |
|---|---|---|
| 1. Profiler | Colonnes, nuls, uniques | df.info(), df.describe(include="all") |
| 2. Normaliser les colonnes | Nettoyer noms/texte | df.columns = df.columns.str.strip().str.lower() |
| 3. Corriger les types | to_datetime, to_numeric, astype("category") | df["date"] = pd.to_datetime(df["date"], errors="coerce") |
| 4. Gérer les manquants | Supprimer ou remplir | df["age"] = df["age"].fillna(df["age"].median()) |
| 5. Gérer les outliers | Capper ou marquer | df["rev_cap"] = df["revenue"].clip(upper=df["revenue"].quantile(0.99)) |
| 6. Dédupliquer | Retirer doublons exacts/partiels | df.drop_duplicates(subset=["id", "date"], keep="last") |
| 7. Valider | Imposer plages/catégories | assert df["score"].between(0,100).all() |
1) Profiler rapidement
summary = {
"rows": len(df),
"columns": df.shape[1],
"nulls": df.isna().sum(),
"unique_counts": df.nunique(),
}- Détecter tôt les types mixtes (
df.info()). - Vérifier les distributions via
df.describe(percentiles=[0.01,0.99]).
2) Normaliser colonnes et texte
df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
df["country"] = df["country"].str.strip().str.title()- Des noms standards simplifient les joins et le code.
- Pour des caractères étranges :
.str.normalize("NFKC").
3) Corriger les types
df["date"] = pd.to_datetime(df["date"], errors="coerce", utc=True)
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
df["segment"] = df["segment"].astype("category")errors="coerce"rend visibles les valeurs incorrectes (NaT/NaN).convert_dtypes()applique des types nullable et économes en mémoire.
4) Traiter les valeurs manquantes
df["age"] = df["age"].fillna(df["age"].median())
df["city"] = df["city"].fillna("Unknown")
df = df.dropna(subset=["id"]) # clé obligatoire- Décider par colonne : numérique → médiane/moyenne ; catégoriel → mode/placeholder.
- Garder le signal avec un flag :
df["age_imputed"] = df["age"].isna().
5) Traiter les outliers
upper = df["revenue"].quantile(0.99)
lower = df["revenue"].quantile(0.01)
df["revenue_capped"] = df["revenue"].clip(lower=lower, upper=upper)- Pour des ratios, filtrez via z-score :
abs(z) < 3. - En finance, capper plutôt que supprimer pour conserver les comptes.
6) Dédupliquer en sécurité
df = df.drop_duplicates(subset=["id", "date"], keep="last")- Vérifier la clé d’unicité :
assert df.duplicated(["id"]).sum() == 0. - Pour du flou, normaliser d’abord (e-mails en minuscules, etc.).
7) Valider avant export
assert df["score"].between(0, 100).all()
valid_segments = {"basic", "pro", "enterprise"}
assert df["segment"].isin(valid_segments).all()- En tests, utilisez
pd.testing.assert_frame_equalpour comparer les sorties. - Ajoutez des checks légers (lignes/nuls) dans les pipelines pour capter les régressions.
Mini pipeline de bout en bout
def clean(df):
df = df.copy()
df.columns = df.columns.str.strip().str.lower()
df["date"] = pd.to_datetime(df["date"], errors="coerce")
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
df["amount"] = df["amount"].fillna(df["amount"].median())
df["segment"] = df["segment"].fillna("unknown").str.lower()
df = df.dropna(subset=["id"])
df = df.drop_duplicates(subset=["id", "date"], keep="last")
assert df["amount"].ge(0).all()
return df- Copier d’abord pour ne pas muter l’entrée.
- Avec
df.pipe(clean), le pipeline reste lisible.
Guides liés
Points clés
- Standardiser les noms, imposer les types, traiter les nuls avec intention.
- Capper ou marquer les outliers plutôt que supprimer silencieusement.
- Valider clés et plages avant d’envoyer vers la BI ou l’analytique.