Nettoyer les données avec Pandas
Le nettoyage transforme un schéma observé en un schéma déclaré. Rendez cette transformation reproductible et les données rejetées visibles.
Pipeline
- Conservez les entrées brutes, ou leur emplacement immuable et leur provenance.
- Normalisez les noms de colonnes et les espaces manifestement superflus.
- Analysez les types avec des formats explicites et un comportement d'échec maîtrisé.
- Résolvez doublons et valeurs manquantes selon les règles métier.
- Validez clés, plages, catégories, unités et invariants entre colonnes.
- Produisez les données nettoyées ainsi qu'un rapport de qualité.
import pandas as pd
raw = pd.DataFrame({
"entity_id": [1, 1, 2],
"email": [" ADA@example.org ", "ada@example.org", "lin@example.org"],
"amount": ["10", "12", "bad"],
"occurred_at": ["2026-01-01", "2026-01-02", "invalid"],
"updated_at": pd.to_datetime(["2026-01-01", "2026-01-02", "2026-01-03"]),
"code": ["AB-01", "AB-02", "CD-03"],
})
clean = (
raw.rename(columns=str.strip)
.assign(
email=lambda x: x["email"].str.strip().str.lower(),
amount=lambda x: pd.to_numeric(x["amount"], errors="coerce"),
occurred_at=lambda x: pd.to_datetime(
x["occurred_at"], format="%Y-%m-%d", errors="coerce", utc=True
),
)
)
errors="coerce" convertit les échecs d'analyse en valeurs manquantes ; cela ne les rend pas acceptables.
Comptez et examinez ces échecs avant de poursuivre.
L’étape suivante sépare les lignes rejetées avant dédoublonnage et validation. Ici, la ligne 2 est rejetée et l’enregistrement le plus récent de l’entité 1 est conservé, avec un montant de 12.
invalid = clean["amount"].isna() | clean["occurred_at"].isna()
rejected = raw.loc[invalid].copy()
clean = clean.loc[~invalid].copy()
Extraction de texte
Préférez les méthodes vectorisées sur les chaînes aux fonctions de rappel Python :
parts = clean["code"].str.extract(r"^(?P<prefix>[A-Z]+)-(?P<number>[0-9]+)\Z")
clean = clean.join(parts)
Les expressions régulières doivent décrire le format accepté, pas seulement trouver une sous-chaîne plausible. Conservez la colonne d'origine jusqu'à la réussite de la validation.
Doublons
Définissez la clé d'entité et l'ordre avant d'appeler drop_duplicates :
clean = (
clean.sort_values("updated_at", kind="stable")
.drop_duplicates(subset=["entity_id"], keep="last")
)
Il s'agit d'une règle métier. Consignez pourquoi la ligne conservée fait autorité.
Valider explicitement
assert clean["entity_id"].notna().all()
assert clean["entity_id"].is_unique
assert clean["amount"].notna().all()
assert clean["amount"].ge(0).all()
Aux frontières de production, préférez un schéma ou une couche de validation réutilisable à un ensemble d'assertions ponctuelles.
Préserver le sens de la validation
Pour distinguer les erreurs de conversion des absences initiales, comparez notna() sur la colonne brute à isna() sur la colonne convertie, avec le même index et avant filtrage. L’extraction renvoie deux colonnes textuelles : convertissez explicitement number pour calculer. [0-9] limite les chiffres à ASCII et \Z impose la fin réelle de la chaîne.
Mettre toute l’adresse électronique en minuscules suppose une règle applicative insensible à la casse, pas une règle universelle d’identité des adresses. Ici, utc=True interprète les dates comme minuit UTC, pas minuit local. Le dédoublonnage suppose des dates de mise à jour converties et présentes ; un tri stable garde la dernière ligne d’entrée en cas d’égalité, seulement si cette règle de départage convient. Python -O désactive les assertions ; les contrôles obligatoires doivent lever des exceptions explicites.