Section 11.2.15 : Analyse exploratoire (EDA) — La méthode complète
🎯 Objectif pédagogique
Maîtriser l'analyse exploratoire de données (EDA) — la démarche structurée pour comprendre un nouveau dataset. Vous serez capable d'analyser n'importe quel jeu de données en 30 minutes et d'en extraire des insights actionnables.
EDA — L'art de poser les bonnes questions aux données
L'analyse exploratoire (Exploratory Data Analysis) est la première étape de tout projet data. Avant de modéliser, prédire ou construire un dashboard, il faut comprendre les données. C'est exactement ce que Marc faisait intuitivement en finance avec les bilans — sauf qu'ici, c'est systématisé.
Étape 1 : Structure et aperçu
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# Charger
df = pd.read_csv("job_applications.csv")
# 1. Forme
print(f"Shape: \{df.shape\}") # (lignes, colonnes)
print(f"Colonnes: \{df.columns.tolist()\}")
# 2. Aperçu
print(df.head(10))
print(df.tail(5))
print(df.sample(5)) # 5 lignes aléatoires
# 3. Types et mémoire
print(df.info())
print(f"Mémoire: \{df.memory_usage(deep=True).sum() / 1024:.1f\} KB")
# 4. Résumé statistique
print(df.describe()) # Nombres
print(df.describe(include='object')) # Texte
Étape 2 : Qualité des données
# Valeurs manquantes
missing = df.isnull().sum()
missing_pct = (missing / len(df) * 100).round(1)
missing_report = pd.DataFrame(\{'count': missing, 'percent': missing_pct\})
print(missing_report[missing_report['count'] > 0].sort_values('percent', ascending=False))
# Visualiser les manquants
plt.figure(figsize=(12, 4))
sns.heatmap(df.isnull(), cbar=False, yticklabels=False, cmap='viridis')
plt.title("Carte des valeurs manquantes")
plt.tight_layout()
plt.show()
# Doublons
print(f"Doublons : \{df.duplicated().sum()\}")
# Valeurs uniques par colonne catégorielle
for col in df.select_dtypes(include='object').columns:
print(f"\{col\}: \{df[col].nunique()\} valeurs uniques")
if df[col].nunique() < 15:
print(f" → \{df[col].value_counts().to_dict()\}")
Étape 3 : Distribution des variables numériques
# Histogrammes pour toutes les variables numériques
numeric_cols = df.select_dtypes(include=np.number).columns
n_cols = len(numeric_cols)
fig, axes = plt.subplots(1, min(n_cols, 4), figsize=(16, 4))
if n_cols == 1:
axes = [axes]
for ax, col in zip(axes, numeric_cols[:4]):
ax.hist(df[col].dropna(), bins=20, edgecolor='white', color='#0891b2')
ax.set_title(col)
ax.axvline(df[col].mean(), color='red', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
# Statistiques détaillées
for col in numeric_cols:
print(f"\n--- \{col\} ---")
print(f" Moyenne: \{df[col].mean():.2f\}")
print(f" Médiane: \{df[col].median():.2f\}")
print(f" Skew: \{df[col].skew():.2f\}") # > 0: right-skewed, < 0: left-skewed
Étape 4 : Relations entre variables
# Matrice de corrélation
plt.figure(figsize=(10, 8))
corr = df.select_dtypes(include=np.number).corr()
mask = np.triu(np.ones_like(corr, dtype=bool))
sns.heatmap(corr, mask=mask, annot=True, fmt='.2f', cmap='coolwarm', center=0)
plt.title("Matrice de corrélation")
plt.tight_layout()
plt.show()
# Corrélations fortes
strong_corr = []
for i in range(len(corr.columns)):
for j in range(i+1, len(corr.columns)):
if abs(corr.iloc[i, j]) > 0.5:
strong_corr.append((corr.columns[i], corr.columns[j], corr.iloc[i, j]))
print("\nCorrélations fortes (|r| > 0.5):")
for c1, c2, r in sorted(strong_corr, key=lambda x: -abs(x[2])):
print(f" \{c1\} ↔ \{c2\}: \{r:.3f\}")
Étape 5 : Insights visuels
# Dashboard EDA en 4 graphiques
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 1. Top 10 entreprises
df['company'].value_counts().head(10).plot(kind='barh', ax=axes[0,0], color='#0891b2')
axes[0,0].set_title("Top 10 entreprises")
# 2. Distribution des salaires
axes[0,1].hist(df['salary'].dropna(), bins=20, color='#0891b2', edgecolor='white')
axes[0,1].set_title("Distribution des salaires")
# 3. Statuts
df['status'].value_counts().plot(kind='pie', ax=axes[1,0], autopct='%1.0f%%')
axes[1,0].set_title("Répartition par statut")
# 4. Candidatures dans le temps
df['date'] = pd.to_datetime(df['date'])
df.groupby(df['date'].dt.to_period('W')).size().plot(ax=axes[1,1], color='#0891b2')
axes[1,1].set_title("Candidatures par semaine")
plt.suptitle("Dashboard EDA — Recherche d'emploi", fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
Le template EDA de Marc
Copiez-collez ce template pour chaque nouveau dataset :
- →
df.shape+df.info()+df.describe()→ 30 secondes - →
df.isnull().sum()+ doublons → 1 minute - →
df.select_dtypes(include='number')+ histogrammes → 2 minutes - →
df.corr()+ heatmap → 1 minute - →4 graphiques clés → 5 minutes Total : 10 minutes pour comprendre n'importe quel dataset.
🏋️ Exercice pratique (25 minutes)
Appliquez l'EDA complet sur un dataset de votre choix :
- →Option A : vos données de Job Tracker
- →Option B : un dataset Kaggle (ex: Titanic, Iris, ou d'offres d'emploi)
Produisez un rapport avec :
- →Shape et types
- →Rapport de qualité (NaN, doublons)
- →3 statistiques clés
- →3 graphiques pertinents
- →2 insights/découvertes
Pourquoi l'EDA est-elle la première étape de tout projet data, avant la modélisation ?
Qu'indique un skew (asymétrie) > 1 pour une variable numérique ?