Nettoyage de Dataset
Vue d'ensemble
Le nettoyage de dataset transforme des données brutes et désordonnées en une forme cohérente et prête pour l'analyse. Chaque opération doit être documentée : ce qui a changé, pourquoi, et combien de lignes/colonnes ont été affectées. Ce n'est pas un script unique — c'est un pipeline reproductible.
Quand l'utiliser
Utilisez cette skill quand :
- Les données brutes ont des valeurs manquantes, des doublons, des types incohérents ou des valeurs aberrantes.
- Les données proviennent de plusieurs sources avec des formats ou des encodages conflictuels.
- Vous avez besoin d'un pipeline de nettoyage documenté, pas un simple
dropna()silencieux. - Le dataset sera utilisé pour la modélisation, l'analyse ou le partage.
Ne l'utilisez pas pour :
- L'analyse exploratoire sans transformation — utilisez d'abord
exploratory-data-analysis. - Les stratégies de partitionnement — utilisez
dataset-splitting. - Le suivi de versions — utilisez
dataset-versioning.
Workflow de nettoyage
1. Stratégie des valeurs manquantes
Choisissez et documentez UNE stratégie par colonne :
| Stratégie | Quand l'utiliser | Risque | ||-------------|------| | Supprimer les lignes | < 5% manquants, lignes indépendantes | Perte de cas rares | | Supprimer la colonne | > 40% manquants et pas critique | Perte de signal | | Imputation moyenne/médiane | Continu, distribution symétrique | Sous-estime la variance | | Imputation du mode | Catégorique, classe dominante claire | Sur-représente la majorité | | Remplissage constant | Valeur par défaut basée sur le domaine | Peut introduire un biais | | Imputation basée sur un modèle | Nombreux manquants, forts prédicteurs | Fuite si non prudent | | Drapeau indicateur | L'absence elle-même est informative | Ajoute de la dimensionnalité |
import pandas as pd
import numpy as np
# JAMAIS faire cela silencieusement :
# df.dropna(inplace=True)
# À la place — auditez d'abord :
missing = df.isnull().sum()
missing_pct = df.isnull().mean() * 100
print(missing_pct[missing_pct > 0].sort_values(ascending=False))
# Imputation documentée avec piste d'audit :
audit = {}
mask = df['age'].isnull()
audit['age_imputed_count'] = mask.sum()
df.loc[mask, 'age'] = df['age'].median()
df['age_imputed'] = mask.astype(int) # drapeau pour sensibiliser les étapes suivantes
2. Déduplication
# Définissez explicitement les colonnes d'identité avant la dédupplication
identity_cols = ['user_id', 'timestamp']
n_before = len(df)
df = df.drop_duplicates(subset=identity_cols, keep='first')
audit['duplicates_removed'] = n_before - len(df)
# Détection de quasi-doublons (floue) :
from difflib import SequenceMatcher
# Utilisez pour les champs texte où la correspondance exacte est trop stricte
3. Normalisation des types
# Normalisation date/heure
df['created_at'] = pd.to_datetime(df['created_at'], utc=True, errors='coerce')
# Normalisation des chaînes
df['category'] = df['category'].str.strip().str.lower().str.replace(r'\s+', '_', regex=True)
# Coercition numérique avec audit
original = df['price'].copy()
df['price'] = pd.to_numeric(df['price'], errors='coerce')
audit['price_coerced_nulls'] = df['price'].isnull().sum() - original.isnull().sum()
4. Gestion des valeurs aberrantes
# Plafonnage basé sur le domaine, pas des percentiles arbitraires
# Exemple : l'âge ne peut pas être < 0 ou > 120
df.loc[df['age'] < 0, 'age'] = np.nan
df.loc[df['age'] > 120, 'age'] = 120 # plafonnez, ne supprimez pas
# Pour les valeurs aberrantes statistiques — utilisez l'IQR avec validation du domaine :
Q1 = df['value'].quantile(0.25)
Q3 = df['value'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 3.0 * IQR # clôture plus large pour une suppression moins agressive
upper = Q3 + 3.0 * IQR
outliers = (df['value'] < lower) | (df['value'] > upper)
audit['outliers_flagged'] = outliers.sum()
df['outlier_flag'] = outliers.astype(int)
5. Encodage catégorique
# One-hot pour < 20 catégories, encodage par label sinon
n_unique = df['category'].nunique()
if n_unique <= 20:
df = pd.get_dummies(df, columns=['category'], drop_first=True)
else:
df['category_code'] = df['category'].astype('category').cat.codes
Piste d'audit
Produisez toujours un journal d'audit structuré :
audit = {
'rows_before': n_before,
'rows_after': n_after,
'columns_before': cols_before,
'columns_after': cols_after,
'missing_handled': {col: strategy for col, strategy in missing_strategies.items()},
'duplicates_removed': dupes,
'outliers_flagged': outliers,
'type_coercions': type_changes,
}
Enregistrez audit à côté du dataset nettoyé en tant que cleaning_audit.json.
Vérification de qualité
Après le nettoyage, vérifiez :
- Aucune colonne n'a > 5% de manquants (sauf documenté comme acceptable).
- Tous les dtypes correspondent à la spécification.
- Aucune ligne d'identité dupliquée n'existe.
- Les colonnes catégoricales ont des valeurs cohérentes et normalisées.
- Le journal d'audit est complet et enregistré avec le dataset.
Techniques avancées (2025-2026)
Pour les datasets au-delà du nettoyage tabulaire simple, combinez avec :
- Déduplication sémantique — skill
embedding-analysispour la suppression de quasi-doublons basée sur le sens à grande échelle (NeMo Curator SemDedup, LSHBloom). - Filtrage basé sur la perplexité — skill
embedding-analysispour le scoring de qualité de style GRAPE avec un modèle de langage de référence. - Scoring de qualité assisté par LLM — skill
llm-assisted-curationpour le scoring clarté/exactitude/utilité par exemple. - Streaming à grande échelle — skill
hf-datasetspour le streaming adossé à Arrow quand les données dépassent la RAM. - Validation de distribution — skill
embedding-analysispour la divergence JS et la distance de Wasserstein entre les splits.
Ceux-ci sont référencés dans la ligne directrice parente dataset-creation-curation-task et doivent être appliqués après le nettoyage standard quand la taille du dataset ou la qualité le justifient.