Section 11.2.16 : Statistiques descriptives — Comprendre les chiffres
🎯 Objectif pédagogique
Maîtriser les statistiques descriptives (moyenne, médiane, écart-type, corrélation) et savoir les interpréter correctement. Vous serez capable de résumer un dataset en quelques métriques clés et d'éviter les erreurs d'interprétation classiques.
Les statistiques : le langage de la data
Marc, en finance, lisait des rapports truffés de "moyenne", "volatilité", "percentile". Mais il avoue : "Je ne comprenais pas toujours la différence entre la moyenne et la médiane, surtout quand ça changeait les conclusions." Les statistiques descriptives sont les fondations de toute analyse.
Mesures de tendance centrale
import numpy as np
import pandas as pd
salaries = pd.Series([42000, 45000, 48000, 52000, 55000, 58000, 65000, 72000, 95000, 250000])
# Moyenne (sensible aux extrêmes)
print(f"Moyenne: \{salaries.mean():,.0f\}€") # 78,200€ ← tirée vers le haut par 250k
# Médiane (robuste aux extrêmes)
print(f"Médiane: \{salaries.median():,.0f\}€") # 56,500€ ← la réalité de la plupart
# Mode (valeur la plus fréquente)
statuts = pd.Series(['applied']*15 + ['interview']*5 + ['offer']*2 + ['rejected']*8)
print(f"Mode: \{statuts.mode()[0]\}") # applied
Mesures de dispersion
# Étendue
print(f"Min: \{salaries.min():,\}€ | Max: \{salaries.max():,\}€")
print(f"Étendue: \{salaries.max() - salaries.min():,\}€")
# Variance et écart-type
print(f"Variance: \{salaries.var():,.0f\}")
print(f"Écart-type: \{salaries.std():,.0f\}€") # Dispersion moyenne autour de la moyenne
# Quartiles et IQR
Q1 = salaries.quantile(0.25)
Q3 = salaries.quantile(0.75)
IQR = Q3 - Q1
print(f"Q1: \{Q1:,.0f\}€ | Q3: \{Q3:,.0f\}€ | IQR: \{IQR:,.0f\}€")
# Percentiles
print(f"10e percentile: \{salaries.quantile(0.10):,.0f\}€")
print(f"90e percentile: \{salaries.quantile(0.90):,.0f\}€")
# Coefficient de variation (dispersion relative)
cv = salaries.std() / salaries.mean() * 100
print(f"CV: \{cv:.1f\}%") # > 30% = forte dispersion
Corrélation — Mesurer les liens entre variables
df = pd.DataFrame(\{
'experience': [0, 1, 2, 3, 4, 5, 6, 7, 8, 10],
'salary': [35000, 42000, 48000, 52000, 58000, 63000, 70000, 78000, 85000, 95000],
'response_days': [15, 12, 10, 14, 8, 7, 9, 5, 3, 2]
\})
# Corrélation de Pearson (-1 à +1)
print(df.corr())
# experience → salary: +0.99 (forte corrélation positive)
# experience → response: -0.92 (forte corrélation négative)
# salary → response: -0.93 (forte corrélation négative)
Interpréter les corrélations
| Valeur r | Interprétation |
|---|---|
| 0.90 - 1.00 | Très forte positive |
| 0.70 - 0.89 | Forte positive |
| 0.40 - 0.69 | Modérée positive |
| 0.00 - 0.39 | Faible positive |
| -0.39 - 0.00 | Faible négative |
| -1.00 - -0.70 | Forte négative |
Corrélation ≠ Causalité !
Plus de glaces vendues → plus de noyades. Corrélation = +0.85. Mais les glaces ne causent pas les noyades. La variable cachée : la chaleur. Marc, en finance : "L'action Apple monte quand il fait beau en Californie — corrélation 0.3 sur 10 ans. Investir sur cette base serait absurde."
Résumé statistique complet
def rapport_statistique(df, colonne):
"""Rapport statistique complet pour une colonne numérique."""
s = df[colonne]
print(f"=== \{colonne\} ===")
print(f" N : \{s.count()\}")
print(f" Moyenne : \{s.mean():,.2f\}")
print(f" Médiane : \{s.median():,.2f\}")
print(f" Écart-type: \{s.std():,.2f\}")
print(f" Min/Max : \{s.min():,.2f\} / \{s.max():,.2f\}")
print(f" Q1/Q3 : \{s.quantile(0.25):,.2f\} / \{s.quantile(0.75):,.2f\}")
print(f" Skew : \{s.skew():.3f\} (\{'droite' if s.skew() > 0 else 'gauche'\})")
print(f" Kurtosis : \{s.kurtosis():.3f\}")
print(f" NaN : \{s.isnull().sum()\}")
rapport_statistique(df, 'salary')
🏋️ Exercice pratique (20 minutes)
import pandas as pd
import numpy as np
# Simuler les données de 50 candidatures
np.random.seed(42)
df = pd.DataFrame(\{
'salary': np.random.normal(65000, 15000, 50).astype(int),
'experience_required': np.random.randint(0, 10, 50),
'response_time': np.random.exponential(10, 50).astype(int),
'match_score': np.random.randint(40, 100, 50)
\})
# 1. Calculez moyenne, médiane, écart-type de chaque colonne
# 2. La médiane est-elle très différente de la moyenne ? Pourquoi ?
# 3. Quelle paire de variables a la plus forte corrélation ?
# 4. Le response_time est-il normalement distribué ? (hint: skew)
Le salaire moyen d'une entreprise est 80 000€ et la médiane est 55 000€. Qu'est-ce que cela indique ?
Que signifie un écart-type élevé ?