Section 11.2.11 : Visualisation avancée — Seaborn et graphiques statistiques
🎯 Objectif pédagogique
Créer des visualisations statistiques élégantes avec Seaborn. Vous serez capable de produire des graphiques de qualité publication — heatmaps, boxplots, distributions — en une ligne de code, là où Matplotlib en demande 15.
Seaborn — La couche élégante de Matplotlib
Marc a produit ses premiers graphiques Matplotlib. Ça fonctionne, mais les paramètres de style prenaient 10 lignes. Seaborn résout ça : des graphiques statistiques beaux par défaut, avec une syntaxe qui comprend directement les DataFrames pandas.
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Style par défaut Seaborn
sns.set_theme(style="whitegrid", palette="muted", font_scale=1.1)
Graphiques de distribution
# Données
np.random.seed(42)
salaries = pd.DataFrame(\{
'salary': np.concatenate([
np.random.normal(55000, 8000, 50), # Junior
np.random.normal(75000, 10000, 50), # Mid
np.random.normal(95000, 12000, 50) # Senior
]),
'level': ['Junior']*50 + ['Mid']*50 + ['Senior']*50
\})
# Histogramme + courbe de densité
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
sns.histplot(data=salaries, x='salary', hue='level', kde=True, ax=axes[0])
axes[0].set_title("Distribution des salaires")
sns.boxplot(data=salaries, x='level', y='salary', palette='viridis', ax=axes[1])
axes[1].set_title("Boxplot par niveau")
sns.violinplot(data=salaries, x='level', y='salary', palette='mako', ax=axes[2])
axes[2].set_title("Violin plot par niveau")
plt.tight_layout()
plt.show()
Boxplot — Comprendre la distribution
┌─────────────┐
│ │ ─── Q3 (75e percentile)
───────┤ BOÎTE ├───── Médiane (50e percentile)
│ │ ─── Q1 (25e percentile)
└─────────────┘
──── Moustaches ──── (1.5 × IQR)
o o Outliers (au-delà)
# Boxplot des salaires par statut de candidature
df = pd.DataFrame(\{
'company': ['Google','Meta','Stripe','Datadog','Mistral AI','OVH','Vercel','BNP','Doctolib','Alan']*3,
'salary': np.random.normal(70000, 15000, 30).astype(int),
'status': np.random.choice(['applied','interview','offer','rejected'], 30)
\})
plt.figure(figsize=(10, 6))
sns.boxplot(data=df, x='status', y='salary',
order=['applied','interview','offer','rejected'],
palette=\{'applied':'#3b82f6','interview':'#f59e0b','offer':'#22c55e','rejected':'#ef4444'\})
plt.title("Salaires proposés par statut de candidature")
plt.xlabel("")
plt.ylabel("Salaire annuel (€)")
plt.show()
Heatmap — Corrélations
# Matrice de corrélation
data = pd.DataFrame(\{
'salary': np.random.normal(70000, 15000, 100),
'experience_required': np.random.randint(0, 10, 100),
'response_time_days': np.random.randint(1, 30, 100),
'company_size': np.random.choice([10, 100, 1000, 10000], 100),
'match_score': np.random.randint(50, 100, 100)
\})
plt.figure(figsize=(8, 6))
corr = data.corr()
sns.heatmap(corr, annot=True, fmt='.2f', cmap='coolwarm', center=0,
square=True, linewidths=0.5)
plt.title("Corrélation entre variables de candidature")
plt.tight_layout()
plt.show()
Graphiques relationnels
# Scatter plot avec régression
plt.figure(figsize=(8, 6))
sns.regplot(data=data, x='experience_required', y='salary',
scatter_kws=\{'alpha': 0.5\}, line_kws=\{'color': 'red'\})
plt.title("Salaire vs Expérience requise")
plt.xlabel("Années d'expérience requises")
plt.ylabel("Salaire (€)")
plt.show()
# Pair plot — toutes les combinaisons
sns.pairplot(data[['salary', 'experience_required', 'match_score']],
diag_kind='kde', plot_kws=\{'alpha': 0.5\})
plt.suptitle("Relations entre variables", y=1.02)
plt.show()
Catégoriques — countplot et barplot
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Countplot (compte automatiquement)
sns.countplot(data=df, x='status',
order=['applied','interview','offer','rejected'],
palette='Set2', ax=axes[0])
axes[0].set_title("Nombre par statut")
# Barplot (calcule la moyenne automatiquement)
sns.barplot(data=df, x='status', y='salary',
order=['applied','interview','offer','rejected'],
palette='Set2', ax=axes[1], estimator='mean', errorbar='sd')
axes[1].set_title("Salaire moyen par statut")
plt.tight_layout()
plt.show()
Seaborn vs Matplotlib — Quand utiliser lequel ?
Seaborn : graphiques statistiques, exploration de données, heatmaps, distributions — quand vous analysez des données. Matplotlib : graphiques très personnalisés, dasboards custom, annotations complexes — quand Seaborn ne suffit pas. En pratique : 80% Seaborn pour l'analyse, 20% Matplotlib pour les finitions.
🏋️ Exercice pratique (20 minutes)
import seaborn as sns
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Créez un dataset de 50 candidatures simulées
np.random.seed(42)
df = pd.DataFrame(\{
'salary': np.random.normal(68000, 15000, 50).astype(int),
'experience': np.random.randint(0, 8, 50),
'status': np.random.choice(['applied','interview','offer','rejected'], 50, p=[0.4,0.3,0.1,0.2]),
'response_days': np.random.exponential(7, 50).astype(int)
\})
# Créez :
# 1. Violin plot des salaires par statut
# 2. Heatmap de corrélation (salary, experience, response_days)
# 3. Scatter plot salary vs experience avec régression
# 4. Countplot des statuts
Quel graphique Seaborn est le plus adapté pour visualiser les corrélations entre plusieurs variables numériques ?
Qu'est-ce qu'un boxplot montre que l'histogramme ne montre pas directement ?