Aller au contenu principal

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

ActionPertinente lorsque
Conserverl'absence elle-même a un sens ou une logique ultérieure la gère
Supprimerla ligne ou colonne est inutilisable et le biais de suppression est acceptable
Remplir par une constanteune sentinelle métier a un sens explicite
Propager vers l'avant ou l'arrièrel'ordre est valide et les valeurs persistent entre observations voisines
Interpolerun modèle défendable relie les points voisins
Modéliser ou imputerl'incertitude et les fuites sont explicitement maîtrisées
df = df.dropna(subset=["required_key"])
df["country"] = df["country"].fillna("unknown")
df["balance"] = df.groupby("account_id")["balance"].ffill()

Les soldes deviennent :

CompteTempsAvantAprès ffill
A11010
A2<NA>10
B1<NA><NA>

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.

Sources

Explorer les liensOuvrir le réseau