dataset-cleaning

Par mkurman · zorai

Nettoyez, normalisez et préparez des jeux de données bruts pour l'analyse ou le ML. Couvre la gestion des valeurs manquantes, la déduplication, le traitement des valeurs aberrantes, la normalisation des types, l'encodage catégoriel et la journalisation des transformations.

npx skills add https://github.com/mkurman/zorai --skill dataset-cleaning

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-analysis pour la suppression de quasi-doublons basée sur le sens à grande échelle (NeMo Curator SemDedup, LSHBloom).
  • Filtrage basé sur la perplexité — skill embedding-analysis pour 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-curation pour le scoring clarté/exactitude/utilité par exemple.
  • Streaming à grande échelle — skill hf-datasets pour le streaming adossé à Arrow quand les données dépassent la RAM.
  • Validation de distribution — skill embedding-analysis pour 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.

Skills similaires