Les données manquantes avec Pandas
Les données manquantes sont omniprésentes dans les jeux de données réels. Elles peuvent provenir de nombreuses causes :
- erreurs de saisie
- données non collectées
- capteurs défaillants
- valeurs non applicables (ex : prix = 0 mais enregistré comme manquant)
INFO
Beaucoup de méthodes statistiques et de modèles de machine learning ne fonctionnent pas avec des valeurs manquantes, ce qui rend leur gestion indispensable.
Comment Pandas représente les données manquantes
Dans Pandas, les valeurs manquantes sont représentées par :
NaN(Not a Number) → données numériquespd.NA→ valeur manquante générique (versions récentes)NaT(Not a Time) → données temporelles (timestamps)
INFO
Pour la majorité des cas pratiques, NaN, NA et NaT sont traités de la même manière.
⚠️ Comparaison et valeurs manquantes
Il est incorrect de tester une valeur manquante avec ==
np.nan == np.nan # False👉 Logique : deux valeurs inconnues ne peuvent pas être comparées.
| Méthode | Rôle |
|---|---|
isna() / isnull() | détecter les valeurs manquantes |
notna() / notnull() | détecter les valeurs présentes |
Les 3 stratégies possibles face aux données manquantes
Il n’existe pas de solution universelle. Le choix dépend toujours du contexte métier et des objectifs.
1️⃣ Conserver les données manquantes
👉 Ne rien faire
| Avantages | Inconvénients |
|---|---|
| aucune modification des données | incompatible avec beaucoup d’algorithmes |
| méthode la plus simple | peut bloquer un pipeline ML |
| respecte la réalité du dataset |
📌 À utiliser si :
- les méthodes suivantes acceptent les NaN
- la valeur manquante a un sens en soi
2️⃣ Supprimer les données manquantes
On peut supprimer :
- des lignes (observations) : Utile si une observation contient trop peu d’informations exploitables
- des colonnes (features) : Pertinent si la majorité des valeurs de cette feature sont manquantes.
⚠️ Risque majeur
perte d’information et limitation des modèles futurs.
Exemple
| Index | Year | Pop | GDP |
|---|---|---|---|
| USA | 1776 | NAN | NAN |
| CANADA | 1867 | 38 | 1.7 |
| MEXICO | 1821 | 126 | 1.22 |
| Index | Year | Pop | GDP |
|---|---|---|---|
| USA | 1776 | 328 | NAN |
| CANADA | 1867 | 38 | NAN |
| MEXICO | 1821 | 126 | 1.22 |
3️⃣ Remplacer / compéter (imputer) les données manquantes
Méthode la plus complexe, mais souvent la plus utile.
| Remplacement simple | Remplacement statistique | Interpolation |
|---|---|---|
| 0 (valeur logique : ex. aucun porte-avions) | moyenne | linéaire |
| catégorie par défaut | médiane | temporelle |
| valeur fixe | mode | ordonnée |
⚠️ Attention
Remplir = inventer une valeur Cela doit être justifié par le contexte métier.
Exemple
Remplacement par 0 :
| Index | Year | Pop | GDP |
|---|---|---|---|
| USA | 1776 | 328 | 20.5 |
| CANADA | 1867 | 38 | NAN |
| MEXICO | 1821 | 126 | NAN |
| Index | Year | Pop | GDP |
|---|---|---|---|
| USA | 1776 | 328 | 20.5 |
| CANADA | 1867 | 38 | 0 |
| MEXICO | 1821 | 126 | 0 |
Remplacement avec une valeur interpolée ou estimée :
| Index | Year | Pop | GDP | Perct |
|---|---|---|---|---|
| USA | 1776 | 328 | 20.5 | 75% |
| CANADA | 1867 | 38 | 1.7 | NAN |
| MEXICO | 1821 | 126 | 1.22 | 25% |
| Index | Year | Pop | GDP | Perct |
|---|---|---|---|---|
| USA | 1776 | 328 | 20.5 | 75% |
| CANADA | 1867 | 38 | 1.7 | 50% |
| MEXICO | 1821 | 126 | 1.22 | 25% |
Fichier Python associé
missing data
"""
missing_data_basics.py
=====================
Gestion des données manquantes avec Pandas
Ce script couvre :
- Détection des valeurs manquantes
- Filtrage conditionnel avec isnull / notnull
- Suppression des données manquantes (dropna)
- Remplacement des données manquantes (fillna)
- Interpolation
"""
import pandas as pd
import numpy as np
# ======================================================
# 1. À quoi ressemblent les valeurs manquantes
# ======================================================
"""
Pandas utilise plusieurs représentations pour les données manquantes :
- np.nan → données numériques (float)
- pd.NA → valeur manquante générique (nullable)
- pd.NaT → données temporelles (timestamp)
pd.NA a été introduit pour unifier la gestion des valeurs manquantes
quel que soit le type de données.
"""
print("=== Valeurs manquantes ===")
print("np.nan :", np.nan)
print("pd.NA :", pd.NA)
print("pd.NaT :", pd.NaT)
print()
# ------------------------------------------------------
# Comparaisons à éviter
# ------------------------------------------------------
print("=== Comparaisons incorrectes ===")
print("np.nan == np.nan :", np.nan == np.nan)
print("np.nan in [np.nan] :", np.nan in [np.nan])
print("np.nan is np.nan :", np.nan is np.nan)
print("pd.NA == pd.NA :", pd.NA == pd.NA)
print()
"""
⚠️ Conclusion :
- Ne JAMAIS utiliser == pour tester une valeur manquante
- Toujours utiliser isna() / notna()
"""
# ======================================================
# 2. Création et exploration d'un DataFrame
# ======================================================
df = pd.read_csv("./data/movie_scores.csv")
print("=== DataFrame initial ===")
print(df)
print()
print("=== Valeurs manquantes (isnull) ===")
print(df.isnull())
print()
print("=== Valeurs présentes (notnull) ===")
print(df.notnull())
print()
# ======================================================
# 3. Filtrage conditionnel avec données manquantes
# ======================================================
print("=== Acteurs avec prénom connu ===")
print(df[df["first_name"].notnull()])
print()
print("=== Score avant film manquant MAIS sexe connu ===")
condition = (
df["pre_movie_score"].isnull()
& df["sex"].notnull()
)
print(df[condition])
print()
# ======================================================
# 4. Suppression des données manquantes (dropna)
# ======================================================
print("=== Suppression des lignes avec au moins un NaN ===")
print(df.dropna())
print()
print("=== Suppression des lignes entièrement NaN ===")
print(df.dropna(how="all"))
print()
print("=== Suppression avec seuil (au moins 1 valeur non nulle) ===")
print(df.dropna(thresh=1))
print()
print("=== Suppression des colonnes avec NaN ===")
print(df.dropna(axis=1))
print()
print("=== Suppression des colonnes avec moins de 4 valeurs non nulles ===")
print(df.dropna(thresh=4, axis=1))
print()
# ======================================================
# 5. Remplacement des données manquantes (fillna)
# ======================================================
print("=== Remplacement global (déconseillé) ===")
print(df.fillna("NEW VALUE!"))
print()
print("=== Remplacement ciblé : first_name ===")
df["first_name"] = df["first_name"].fillna("Empty")
print(df["first_name"])
print()
print("=== Remplacement par la moyenne ===")
mean_score = df["pre_movie_score"].mean()
print("Moyenne pre_movie_score :", mean_score)
df["pre_movie_score"] = df["pre_movie_score"].fillna(mean_score)
print(df["pre_movie_score"])
print()
print("=== Remplacement automatique (numérique uniquement) ===")
print(df.fillna(df.mean(numeric_only=True)))
print()
# ======================================================
# 6. Interpolation
# ======================================================
"""
L’interpolation permet d’estimer une valeur manquante
en fonction des valeurs voisines.
⚠️ À utiliser uniquement si l’ordre des données est pertinent.
"""
airline_tix = {
"economy": 30,
"economy_plus": 50,
"business": np.nan,
"first": 100
}
ser = pd.Series(airline_tix)
print("=== Série originale ===")
print(ser)
print()
print("=== Interpolation linéaire ===")
print(ser.interpolate())
print()
# Interpolation sur DataFrame
df_prices = pd.DataFrame(ser, columns=["Price"]).reset_index()
print("=== Interpolation spline (ordre 2) ===")
print(df_prices.interpolate(method="spline", order=2))
print()