Valeurs manquantes
Un solde manquant ne permet pas de savoir si le compte est vide ou si son solde n’a jamais été observé. La cause de l’absence détermine si un remplissage est justifié. Pandas fournit une API commune pour plusieurs représentations, dont pd.NA, NaN et NaT.
Détecter
import pandas as pd
df = pd.DataFrame({
"required_key": [1, 2, 3], "country": ["CA", None, "FR"],
"account_id": ["A", "A", "B"], "time": [1, 2, 1],
"balance": pd.Series([10, pd.NA, pd.NA], dtype="Int64"),
}).sort_values(["account_id", "time"])
missing_by_column = df.isna().sum()
complete_rows = df.notna().all(axis="columns")
Avant remplissage, missing_by_column compte deux soldes et un pays manquants ; les autres colonnes sont complètes. complete_rows n’est vrai que pour la première ligne.
Utilisez isna et notna : l'égalité avec une sentinelle d'absence n'est pas un test fiable.
Examinez à la fois nombres et taux, puis ventilez-les par cohortes pertinentes si le total peut masquer un motif systématique.
Choisir une règle
df = df.dropna(subset=["required_key"])
df["country"] = df["country"].fillna("unknown")
df["balance"] = df.groupby("account_id")["balance"].ffill()
Les soldes deviennent :
La deuxième ligne de A reprend le solde 10 de l’observation précédente du même compte. B n’a aucun solde antérieur dans son groupe : il reste manquant, sans recevoir le 10 de A. Toutes les clés obligatoires sont présentes, donc dropna ne supprime aucune ligne ; le pays manquant devient "unknown". dropna et fillna renvoient des résultats par défaut ; les affectations mettent explicitement df à jour.
Triez selon les clés d'entité et de temps pertinentes avant une propagation directionnelle. Ne propagez jamais accidentellement entre les groupes.
Types et réductions
Les types d'extension nullables tels que Int64, boolean et string conservent les types sémantiques
tout en représentant l'absence. Précisez-les aux frontières importantes au lieu de dépendre de l'inférence.
De nombreuses réductions ignorent les valeurs manquantes par défaut. Définissez explicitement skipna
ou le nombre minimal requis (min_count) si cette valeur par défaut change le sens du résultat.
Inconnu ne signifie ni zéro ni faux
Les règles des données manquantes touchent aussi la logique : pd.NA == pd.NA reste inconnu et bool(pd.NA) lève TypeError. Chaînes vides et infinis ne sont pas manquants par défaut. Une somme entièrement manquante vaut zéro sauf si un nombre minimal de valeurs valides est imposé. Une comparaison nullable suivie de .all() peut ignorer les inconnus ; vérifiez séparément la présence des valeurs obligatoires.
empty = pd.Series([pd.NA, pd.NA], dtype="Int64")
assert empty.sum() == 0
assert pd.isna(empty.sum(min_count=1))
assert empty.ge(0).all()
assert not empty.notna().all()
Consigner la décision
Un pipeline de nettoyage doit indiquer quelles colonnes peuvent être manquantes, pourquoi, et l'effet de chaque règle sur l'analyse en aval. Conservez une colonne indicatrice lorsque l'imputation peut elle-même fournir une information prédictive ou diagnostique.