Données d’entraînement: Explorer les données
Les données, c’est le carburant de l’IA. Mais comme pour une voiture, on peut pas juste balancer n’importe quoi dans le réservoir et espérer que ça roule. Avant de faire tourner des modèles ML, il faut d’abord comprendre ce qu’on a entre les mains. Cette exploration, c’est un peu comme ouvrir le capot pour voir l’état du moteur.
Les notebooks : notre laboratoire de data science
Pour explorer les données, on va utiliser un outil qui cartonne dans le domaine : les notebooks Jupyter. C’est un environnement qui mélange code Python, visualisations et texte explicatif dans un seul document. En gros, on peut coder, voir ses graphiques directement et prendre des notes, le tout dans une interface web interactive.
Les notebooks révolutionnent la façon de bosser avec les données. On écrit du code dans des cellules, on l’exécute, et hop, les résultats s’affichent juste en dessous. Fini les allers-retours entre son éditeur de code et une fenêtre de terminal. Ça ressemble à un PDF interactif où chaque bout de code peut être modifié et relancé à la volée.
Cette approche change complètement le workflow. Au lieu de coder “à l’aveugle” et de découvrir les résultats à la fin, on explore ses données étape par étape. On peut tester une hypothèse, voir immédiatement si elle tient la route, et ajuster son approche en temps réel.
Le dataset UCI Heart Disease : un cas d’étude réaliste
Pour illustrer l’exploration de données, on va bosser sur un dataset classique : Heart Disease. Ce jeu de données contient des informations médicales pour prédire si une personne risque de développer une maladie cardiaque. Parfait pour apprendre, car il présente les défis typiques qu’on rencontre en vrai.
Le dataset se trouve dans
/mnt/ch1/heart_disease.csv et contient 920 patients avec 16 variables différentes : âge, sexe, type de douleur thoracique, tension artérielle, cholestérol, etc. L’objectif ? Prédire si le patient a une maladie cardiaque (variable num).Mais attention, ce dataset arrive tout droit du monde réel. Il contient donc des valeurs manquantes, des doublons potentiels, des erreurs de saisie, et d’autres joyeusetés qui peuvent faire planter tes modèles. C’est exactement le genre de situation qu’on rencontre sur le terrain.
Les données sales : la réalité du terrain
Dans le monde parfait des tutos YouTube, les datasets sont propres, bien formatés, sans valeurs manquantes. Dans la vraie vie ? C’est le chaos. Les données arrivent souvent dans un état déplorable :
- Les valeurs manquantes représentent le problème numéro un. Un capteur qui déconne, un formulaire pas entièrement rempli, une base de données corrompue… Les trous dans les données sont partout. Parfois c’est 5% des valeurs, parfois c’est 40%.
- Les doublons polluent les datasets, surtout quand plusieurs sources alimentent la même base. Un patient qui consulte deux fois le même mois peut se retrouver enregistré en double avec des infos légèrement différentes. Dans notre cas, certains patients peuvent apparaître plusieurs fois avec des mesures prises à des moments différents.
- Les erreurs de saisie créent des aberrations : des âges négatifs, des tensions artérielles à 500, des codes pays fantaisistes. Ces outliers extrêmes peuvent complètement biaiser tes modèles.
- Les formats incohérents compliquent l’analyse. Les dates en DD/MM/YYYY et MM/DD/YYYY dans le même fichier, les noms en majuscules et minuscules mélangées, les unités de mesure différentes selon les colonnes.
Cette pollution des données n’est pas un détail technique. Elle peut faire la différence entre un modèle qui fonctionne et un modèle qui part en vrille. D’où l’importance de cette étape d’exploration et de nettoyage.
ydata_profiling : l’outil qui révèle tout
Pour explorer efficacement nos données, on va utiliser
ydata_profiling. Cette librairie génère automatiquement un rapport complet sur ton dataset. En une seule ligne de code, on obtient une analyse détaillée de chaque variable directement dans un notebook.import pandas as pd
from ydata_profiling import ProfileReport
# Charger les données
df = pd.read_csv('/mnt/ch1/heart_disease.csv')
# Générer le rapport d'exploration dans le notebook
profile = ProfileReport(df, title="UCI Heart Disease - Exploration")
profile.to_notebook_iframe()
Le rapport généré contient une mine d’informations. Pour chaque colonne, on y voit la distribution des valeurs, les statistiques descriptives, les valeurs manquantes, les doublons potentiels.
- La section “Variables” montre des histogrammes pour les variables numériques et des graphiques en barres pour les catégorielles.
- La partie “Interactions” révèle les corrélations entre variables. C’est là qu’apparaît la fameuse matrice de corrélation, ce tableau qui montre comment chaque variable influence les autres. Les corrélations fortes (proches de 1 ou -1) indiquent des relations linéaires, tandis que les valeurs proches de 0 suggèrent une indépendance.
Seaborn et matplotlib : nos outils de visualisation sur mesure
ydata_profiling génère un rapport complet, mais parfois on a besoin de plus de contrôle. C’est là qu’interviennent seaborn et matplotlib, les deux librairies de référence pour créer des visualisations en Python. Matplotlib, c’est le moteur graphique de base, tandis que seaborn apporte une couche esthétique moderne et des fonctions statistiques intégrées.
Ces outils permettent de créer des graphiques personnalisés répondant à nos questions spécifiques. Plutôt que de subir le format imposé par ydata_profiling, on peut ajuster chaque détail : couleurs, tailles, filtres, groupements. En data science, cette flexibilité devient vite indispensable quand on veut creuser certains aspects des données.
Exemples de fonctions SeaBorn
# Exemples d'utilisation plot_histogram(df, 'age') # Distribution d'une variable plot_histogram(df, ['age', 'trestbps']) # Comparer deux distributions plot_scatter(df, 'age', 'chol', hue='sex') # Relation avec couleur par sexe plot_boxplot(df, 'trestbps', by='cp') # Tension par type de douleur plot_correlation(df) # Matrice complète
Ces fonctions compactes donnent un contrôle total sur l’exploration. Contrairement à ydata_profiling qui génère tout d’un coup, ici on choisit exactement quoi visualiser et comment. C’est particulièrement utile pour répondre aux questions analytiques précises ou préparer des graphiques pour une présentation.
Poser les bonnes questions : analyser les patterns
L’exploration de données, c’est aussi savoir quelles questions poser. Avec notre dataset cardiaque, plusieurs interrogations émergent naturellement :
- Le sexe influence-t-il la sévérité des maladies cardiaques ? Cette question nous amène à comparer les distributions de la sévérité de la maladie entre hommes et femmes. On peut s’attendre à des différences, car les maladies cardiaques affectent différemment les deux sexes.
- Comment l’âge se relate-t-il à la sévérité de la maladie ? L’intuition suggère que l’âge et les problèmes cardiaques sont liés, mais quelle est la nature exacte de cette relation ? Linéaire ? Exponentielle ? Y a-t-il des seuils d’âge critiques ?
- Existe-t-il des profils de patients à risque ? En croisant plusieurs variables (âge, sexe, cholestérol, tension), peut-on identifier des combinaisons particulièrement dangereuses ?
Ces questions guident nos visualisations et nos analyses statistiques. Chaque graphique doit répondre à une interrogation précise plutôt que de simplement “faire joli”.
Graphiques usuels : raconter l’histoire des données
Au-delà de la matrice de corrélation, plusieurs visualisations permettent de comprendre nos données :
Les histogrammes montrent la distribution des variables numériques. On voit immédiatement si nos données suivent une loi normale, si elles sont biaisées, s’il y a des pics suspects.

Les boxplots révèlent les outliers et les quartiles. Parfait pour détecter les valeurs aberrantes qui pourraient polluer nos modèles.

Les scatter plots illustrent les relations entre deux variables numériques. Plus parlant qu’un simple coefficient de corrélation, on voit la forme exacte de la relation.

La matrice de corrélation révèle quelles variables bougent ensemble et dans quel sens. Pour notre dataset cardiaque, on pourrait découvrir que l’âge corrèle positivement avec le risque de maladie, ou que certains types d’exercice corrèlent négativement.
Cette visualisation utilise un code couleur intuitif : bleu pour les corrélations négatives, rouge pour les positives, blanc pour les neutres. Plus la couleur est intense, plus la corrélation est forte. On peut repérer d’un coup d’œil les variables redondantes (corrélation proche de 1) et celles qui s’opposent (corrélation proche de -1).

L’exemple typique d’une corrélation positive est celle entre l’âge et la pression artérielle : plus une personne vieillit, plus sa tension tend à augmenter (oldpeak), créant une corrélation proche de +1. À l’inverse, on observe des corrélations négatives comme celle entre l’âge et la fréquence cardiaque maximale (thal) : plus on vieillit, plus notre capacité cardiaque maximale diminue naturellement.
Le raffinement : transformer les données brutes en or
Une fois l’exploration terminée, place au nettoyage. Cette étape transforme nos données sales en dataset exploitable. Mais attention, on va y aller étape par étape car chaque problème nécessite une approche différente.
Étape 1 : La déduplication – éliminer les doublons
Les doublons sont le premier ennemi à combattre. Ils biaisent les statistiques et peuvent faire croire à notre modèle qu’un pattern est plus fréquent qu’il ne l’est vraiment.
# D'abord, regardons la taille de notre dataset
print(f"Taille originale du dataset : {df.shape}")
print(f"Nombre de lignes : {df.shape[0]}")
print(f"Nombre de colonnes : {df.shape[1]}")
# Chercher les doublons parfaits (toutes les colonnes identiques)
doublons_parfaits = df.duplicated()
print(f"Nombre de doublons parfaits : {doublons_parfaits.sum()}")
if doublons_parfaits.sum() > 0:
print("Exemples de lignes dupliquées :")
print(df[doublons_parfaits].head())
# Supprimer les doublons parfaits
df_sans_doublons = df.drop_duplicates()
print(f"Après suppression des doublons : {df_sans_doublons.shape[0]} lignes")
Parfois, les doublons ne sont pas parfaits. Deux patients peuvent avoir les mêmes caractéristiques démographiques mais des mesures cliniques légèrement différentes. Dans ce cas, il faut décider au cas par cas.
Étape 2 : Traiter les valeurs manquantes avec isnull()
Les valeurs manquantes sont partout dans les données réelles. Python les représente par `NaN` (Not a Number). La méthode `isnull()` permet de les détecter.
# Identifier toutes les valeurs manquantes
valeurs_manquantes = df_sans_doublons.isnull().sum()
print("Valeurs manquantes par colonne :")
print(valeurs_manquantes)
# Voir le pourcentage de valeurs manquantes
pourcentage_manquant = (df_sans_doublons.isnull().sum() / len(df_sans_doublons)) * 100
print("\nPourcentage de valeurs manquantes :")
for col, pct in pourcentage_manquant.items():
if pct > 0:
print(f"{col}: {pct:.1f}%")
Pour les variables numériques, on peut remplacer les valeurs manquantes par la moyenne (si les données suivent une distribution normale) ou la médiane (plus robuste aux outliers).
# Remplacer les valeurs manquantes numériques par la médiane
df_propre = df_sans_doublons.copy()
# Exemple avec la colonne cholestérol si elle a des valeurs manquantes
if 'chol' in df_propre.columns and df_propre['chol'].isnull().sum() > 0:
mediane_chol = df_propre['chol'].median()
df_propre['chol'].fillna(mediane_chol, inplace=True)
print(f"Valeurs manquantes cholestérol remplacées par {mediane_chol}")
Pour les variables catégorielles, on utilise le mode (la valeur la plus fréquente).
# Remplacer les valeurs manquantes catégorielles par le mode
colonnes_categorielles = ['sex', 'cp', 'fbs', 'restecg', 'exang', 'slope', 'thal']
for col in colonnes_categorielles:
if col in df_propre.columns and df_propre[col].isnull().sum() > 0:
mode_col = df_propre[col].mode()[0] # mode() renvoie une série, on prend le premier élément
df_propre[col].fillna(mode_col, inplace=True)
print(f"Valeurs manquantes {col} remplacées par {mode_col}")
Étape 3 : Gérer les outliers – les valeurs aberrantes
Les outliers sont des valeurs extrêmes qui peuvent fausser nos analyses. Ils peuvent être dus à des erreurs de saisie ou représenter des cas réellement exceptionnels.
# Identifier les outliers avec des statistiques descriptives
print("Statistiques des variables numériques :")
print(df_propre.describe())
# Chercher les valeurs suspectes dans la tension artérielle
if 'trestbps' in df_propre.columns:
tension_stats = df_propre['trestbps'].describe()
print(f"\nTension artérielle - Min: {tension_stats['min']}, Max: {tension_stats['max']}")
# Valeurs anormalement hautes ou basses
tension_extreme_haute = df_propre[df_propre['trestbps'] > 250]
tension_extreme_basse = df_propre[df_propre['trestbps'] < 50]
print(f"Patients avec tension > 250: {len(tension_extreme_haute)}")
print(f"Patients avec tension < 50: {len(tension_extreme_basse)}")
# Supprimer ou corriger les outliers extrêmes
# Ici on supprime les valeurs impossibles pour la tension
if 'trestbps' in df_propre.columns:
taille_avant = len(df_propre)
df_propre = df_propre[(df_propre['trestbps'] >= 50) & (df_propre['trestbps'] <= 250)]
taille_apres = len(df_propre)
print(f"Outliers supprimés: {taille_avant - taille_apres} lignes")
# Même traitement pour d'autres variables si nécessaire
if 'chol' in df_propre.columns:
# Cholestérol négatif = impossible
df_propre = df_propre[df_propre['chol'] >= 0]
Étape 4 : Convertir les types de données
Enfin, il faut s’assurer que chaque variable a le bon type. Les variables catégorielles doivent être de type `category`, pas `object` ou `int`.
# Convertir les variables catégorielles
colonnes_categorielles = ['sex', 'cp', 'fbs', 'restecg', 'exang', 'slope', 'thal']
for col in colonnes_categorielles:
if col in df_propre.columns:
df_propre[col] = df_propre[col].astype('category')
print(f"{col} converti en type category")
# Vérifier les types finaux
print("\nTypes de données après nettoyage :")
print(df_propre.dtypes)
L’impact sur la performance des modèles
La qualité des données impacte directement les performances de nos modèles. Un dataset sale produit des prédictions erratiques, une généralisation faible, des métriques trompeuses. En revanche, des données bien préparées permettent aux algorithmes d’apprendre des patterns réels plutôt que du bruit.
Cette étape d’exploration et de nettoyage représente souvent 60% du temps d’un projet data science. C’est moins glamour que coder des réseaux de neurones, mais c’est la fondation qui détermine le succès ou l’échec d’un projet.
Les outils comme ydata_profiling automatisent une partie de cette exploration, mais notre œil critique reste indispensable. On doit interpréter les graphiques, identifier les anomalies, prendre les bonnes décisions de nettoyage. C’est là que l’expertise humaine fait la différence.
Résumé: de l’exploration au dataset propre
L’exploration de données, c’est un peu comme faire le diagnostic d’une voiture avant de partir en road trip. Tu ouvres le capot, tu vérifies les niveaux, tu identifies les pièces défaillantes. Les notebooks Jupyter deviennent ton atelier, ydata_profiling ton scanner diagnostique, et les visualisations tes témoins lumineux qui t’alertent sur les problèmes. Cette phase révèle les patterns cachés dans tes données mais aussi leurs défauts : doublons, valeurs manquantes, outliers aberrants.
Le raffinement qui suit transforme ce diagnostic en actions concrètes. Chaque étape – déduplication, imputation des valeurs manquantes, gestion des outliers, conversion des types – résout un problème spécifique avec une approche méthodique. Au final, notre dataset passe de l’état “tout droit sorti de la base de production” à “prêt pour l’entraînement ML”. Cette transformation peut paraître fastidieuse, mais c’est elle qui détermine si nos modèles apprendront des patterns utiles ou du bruit parasite. Un dataset propre, c’est la garantie que notre IA va apprendre sur du solide plutôt que sur du sable.
Exercice pratique : nettoyage du dataset Titanic
Maintenant, c’est à ton tour de jouer ! Le dataset Titanic est parfait pour s’entraîner : il contient des passagers du célèbre navire avec leurs caractéristiques (âge, sexe, classe, prix du billet…) et si ils ont survécu au naufrage. Ce dataset est réputé pour ses données sales : doublons suspects, valeurs manquantes dans plusieurs colonnes, outliers dans les prix des billets.
- Exploration initiale
- Génère un rapport ydata_profiling du dataset brut
- Identifie les colonnes avec des valeurs manquantes
- Repère les variables qui semblent avoir des outliers
- Pose-toi des questions analytiques : “L’âge influence-t-il la survie ?”, “Les femmes survivent-elles plus que les hommes ?”, “La classe du billet impact-il la survie ?”
- Déduplication
- Recherche les doublons parfaits avec `duplicated()`
- Attention : certains passagers peuvent avoir le même nom (famille) mais être des personnes différentes
- Utilise plusieurs colonnes pour identifier les vrais doublons (nom + âge + classe par exemple)
- Traitement des valeurs manquantes
- Variable `Age` : utilise la médiane (plus robuste que la moyenne)
- Variable `Embarked` (port d’embarquement) : utilise le mode
- Variable `Cabin` : cette colonne a énormément de valeurs manquantes, réfléchis si tu la gardes ou la supprimes
- Gestion des outliers
- Variable `Fare` (prix du billet) : certains prix sont anormalement élevés ou bas
- Variable `Age` : vérifie s’il y a des âges impossibles (négatifs, > 150 ans)
Cet exercice te fera passer de spectateur à acteur du nettoyage de données. Tu vas galèrer sur certains choix (faut-il supprimer cette ligne bizarre ou la corriger ?), et c’est normal ! C’est exactement ce genre de dilemmes qu’on rencontre en vrai sur des projets data science!
