Découvrez pourquoi se passer des lois paramétriques
Vous mesurez le temps de chargement d’une page web sur douze visites. Onze valeurs tournent autour de 130 millisecondes, et la douzième affiche 2 400 ms, parce que le réseau du visiteur a flanché. La moyenne vaut alors 321 ms, soit plus du double de presque toutes les observations. Faut-il jeter la valeur ? Changer d’indicateur ? Changer de méthode ?
Ce chapitre pose les bases du cours. Il commence par un rappel des outils de probabilités (c’est par là que commençait le cours suivi au RIT), puis montre pourquoi les méthodes fondées sur la loi normale sont fragiles, et présente l’idée centrale de la statistique non paramétrique : raisonner sur les rangs des observations plutôt que sur leurs valeurs.
Rappels : décrire une variable aléatoire avec scipy.stats
Section intitulée « Rappels : décrire une variable aléatoire avec scipy.stats »Une variable aléatoire (random variable) est une quantité dont la valeur est inconnue mais décrite par des probabilités. L’outil qui la décrit entièrement est sa fonction de répartition (cumulative distribution function, cdf) :
c’est-à-dire la probabilité que prenne une valeur inférieure ou égale à . Elle est croissante (au sens large), continue à droite, tend vers 0 en et vers 1 en .
Le cas discret : la fonction de masse
Section intitulée « Le cas discret : la fonction de masse »Pour une variable discrète, on décrit la loi par sa fonction de masse (probability mass function, pmf) . La fonction de répartition est alors en escalier : constante par morceaux, elle saute de en chaque valeur possible.
Avec une loi discrète, les bornes comptent. , alors que . Pour inclure la borne gauche, il faut retrancher la limite à gauche au lieu de .
Le cas continu : la densité
Section intitulée « Le cas continu : la densité »Pour une variable continue, on utilise la densité (probability density function, pdf) , et . Ici, inclure ou non les bornes ne change rien, car .
Quantiles
Section intitulée « Quantiles »Le quantile d’ordre (avec ) est la valeur telle que : une proportion de la loi se trouve en dessous. La médiane est . Pour une loi discrète, où l’équation n’a pas toujours de solution, on prend .
Dans scipy.stats, chaque loi est un objet qui expose les mêmes méthodes :
from scipy import stats
X = stats.binom(3, 0.5)print(X.pmf(1)) # P(X = 1) = 0.375print(X.cdf(2)) # P(X <= 2) = 0.875
Z = stats.norm() # loi normale centrée réduiteprint(Z.pdf(0)) # densité en 0, environ 0.399print(Z.ppf(0.05)) # quantile d'ordre 5 % (inverse de cdf), environ -1.645print(Z.sf(1.96)) # fonction de survie 1 - F, environ 0.025print(Z.isf(0.025)) # inverse de sf, environ 1.96La méthode ppf (percent point function) est l’inverse de cdf, sf (survival function) vaut et isf est son inverse.
Quand la loi normale ne tient plus
Section intitulée « Quand la loi normale ne tient plus »Beaucoup de lois usuelles appartiennent à une famille position-échelle (location-scale family) : leur densité s’écrit
où est une densité de référence fixe, un paramètre de position (qui décale la courbe) et un paramètre d’échelle (qui l’étire). La loi normale en est l’exemple type, avec et ; les lois de Cauchy et de Laplace aussi. Dans scipy, ce sont les arguments loc et scale de toutes les lois.
D’autres paramètres changent la forme elle-même : on parle de paramètres de forme (shape parameters). Le nombre de degrés de liberté de la loi de Student en est un : pour , on obtient la loi de Cauchy, et quand , on retrouve la loi normale. Plus est petit, plus les queues de la loi sont lourdes, c’est-à-dire plus les valeurs extrêmes sont fréquentes.
La loi de Cauchy est un cas limite instructif : elle n’a pas d’espérance. La moyenne d’un échantillon de Cauchy ne se stabilise jamais, quelle que soit la taille de l’échantillon, alors que sa médiane converge sans problème vers le centre de la loi. Toute méthode fondée sur la moyenne et la variance s’effondre.
Moyenne ou médiane ?
Section intitulée « Moyenne ou médiane ? »L’espérance se calcule par (cas discret) ou (cas continu). Elle ne coïncide avec la médiane que pour une loi symétrique. Pour la loi exponentielle de moyenne 1, la médiane vaut : la longue queue à droite tire la moyenne vers le haut.
Paramétrique ou non paramétrique ?
Section intitulée « Paramétrique ou non paramétrique ? »Une méthode paramétrique suppose que les données viennent d’une famille de lois connue, décrite par quelques paramètres (souvent la loi normale, avec et ), puis raisonne sur ces paramètres. Le test t de Student, l’ANOVA et la corrélation de Pearson, vus dans le cours de Statistiques, en sont des exemples.
Une méthode non paramétrique ne suppose presque rien sur la forme de la loi : typiquement, que les observations sont indépendantes, que la loi est continue, parfois qu’elle est symétrique. On l’appelle aussi méthode « libre de distribution » (distribution-free), parce que la loi de la statistique de test sous l’hypothèse nulle ne dépend pas de la loi des données.
Elle devient le bon choix dans plusieurs situations :
| Situation | Exemple | Pourquoi le paramétrique souffre |
|---|---|---|
| Petit échantillon | 8 patients, 6 plis de validation croisée | impossible de vérifier la normalité, le théorème central limite ne joue pas encore |
| Loi asymétrique | latences, revenus, durées de session | la moyenne et l’écart-type résument mal la loi |
| Valeurs aberrantes | une mesure à 2 400 ms | une seule valeur déplace la moyenne et gonfle la variance |
| Données ordinales | notes de satisfaction de 1 à 5 | l’écart entre « 1 » et « 2 » n’a pas de sens numérique |
Et le prix à payer ? Quand les données sont vraiment normales, un test de rang est un peu moins puissant que le test t. On le mesure par l’efficacité relative asymptotique (asymptotic relative efficiency, ARE) : pour Wilcoxon face au test t sous normalité, elle vaut . Autrement dit, il faut environ 5 % d’observations en plus pour obtenir la même puissance. En contrepartie, pour une loi à queues lourdes, l’ARE dépasse largement 1 (elle vaut 1,5 pour la loi de Laplace, et elle est infinie pour Cauchy), et elle ne descend jamais sous pour une loi continue symétrique. L’assurance est donc peu chère.
Les rangs, outil de base
Section intitulée « Les rangs, outil de base »L’idée centrale est de remplacer chaque observation par son rang : sa position dans l’échantillon trié par ordre croissant. La plus petite valeur reçoit le rang 1, la plus grande le rang .
Pour nos temps de chargement, la valeur 2 400 ms reçoit le rang 12, exactement comme l’aurait fait une valeur de 143 ms. Son caractère extrême disparaît : elle compte comme « la plus grande », sans plus. C’est ce qui rend les méthodes de rang robustes aux valeurs aberrantes.
Les rangs ont une deuxième propriété précieuse : ils sont invariants par toute transformation croissante. Que vous mesuriez en millisecondes, en secondes ou en logarithme de secondes, les rangs sont les mêmes, donc le résultat d’un test de rang aussi.
Les ex aequo
Section intitulée « Les ex aequo »Quand plusieurs valeurs sont égales (ties), on leur attribue la moyenne des rangs qu’elles occuperaient. Pour l’échantillon 3,1 ; 1,2 ; 5,0 ; 3,1 ; 2,7, les deux valeurs 3,1 occupent les places 3 et 4, et reçoivent chacune le rang 3,5 :
| Valeur | 3,1 | 1,2 | 5,0 | 3,1 | 2,7 |
|---|---|---|---|---|---|
| Rang | 3,5 | 1 | 5 | 3,5 | 2 |
Les ex aequo compliquent un peu les lois exactes des statistiques de rang ; les logiciels appliquent alors des corrections, et basculent souvent vers une approximation.
Statistiques d’ordre et fonction de répartition empirique
Section intitulée « Statistiques d’ordre et fonction de répartition empirique »Les valeurs triées s’appellent les statistiques d’ordre. La médiane, les quartiles et l’étendue en découlent directement.
Elles permettent aussi de définir la fonction de répartition empirique (empirical cumulative distribution function, ECDF) :
où vaut 1 si l’observation est inférieure ou égale à , et 0 sinon. C’est simplement la proportion d’observations inférieures ou égales à : une fonction en escalier qui monte de à chaque observation. Elle estime sans aucune hypothèse, et c’est la brique de base du test de Kolmogorov-Smirnov (chapitre 6) et du bootstrap (chapitre 7).
import numpy as npfrom scipy import stats
lat = np.array([120, 135, 128, 142, 131, 125, 138, 129, 2400, 133, 127, 140])print(lat.mean(), np.median(lat)) # 320.67 et 132.0print(stats.rankdata(lat)) # la valeur 2400 reçoit le rang 12print(stats.rankdata([3.1, 1.2, 5.0, 3.1, 2.7])) # [3.5 1. 5. 3.5 2.]
ecdf = stats.ecdf(lat) # disponible à partir de SciPy 1.11print(ecdf.cdf.evaluate(130)) # proportion des valeurs <= 130 : 5/12En R, les mêmes outils s’écrivent :
lat <- c(120, 135, 128, 142, 131, 125, 138, 129, 2400, 133, 127, 140)mean(lat); median(lat)rank(lat) # ex aequo : rang moyen par défautFn <- ecdf(lat)Fn(130) # 5/12En résumé
Section intitulée « En résumé »- Une loi est décrite par sa fonction de répartition , par sa fonction de masse (cas discret) ou sa densité (cas continu) ; avec une loi discrète, attention aux bornes des intervalles.
- Les quantiles inversent ; dans
scipy.stats,ppfinversecdfetisfinversesf. - Les lois à queues lourdes (Student à faible , Cauchy) rendent la moyenne et la variance instables ; la médiane résiste.
- Une méthode non paramétrique remplace l’hypothèse de forme par des hypothèses faibles ; son coût sous normalité est faible (ARE de pour Wilcoxon).
- Les rangs sont robustes aux valeurs aberrantes et invariants par transformation croissante ; les ex aequo reçoivent le rang moyen.
- La fonction de répartition empirique estime sans hypothèse et sert de base à Kolmogorov-Smirnov et au bootstrap.
Exercices
Section intitulée « Exercices »Exercice · Bornes et loi discrète
facilesuit la loi . Calculez , , et .
Voir la solution
Avec pour :
- ;
- (c’est la limite à gauche ) ;
- ;
- .
Les deux derniers résultats diffèrent d’une masse : pour une loi discrète, inclure ou non une borne change le résultat.
En code
from scipy import stats
X = stats.binom(3, 0.5)print(X.cdf(1)) # P(X <= 1) = 0.5print(X.cdf(0)) # P(X < 1) = P(X <= 0) = 0.125print(X.pmf(1) + X.pmf(2)) # P(1 <= X <= 2) = 0.75print(X.cdf(2) - X.cdf(1)) # P(1 < X <= 2) = 0.375pbinom(1, 3, 0.5) # P(X <= 1) = 0.5pbinom(0, 3, 0.5) # P(X < 1) = 0.125sum(dbinom(1:2, 3, 0.5)) # P(1 <= X <= 2) = 0.75pbinom(2, 3, 0.5) - pbinom(1, 3, 0.5) # P(1 < X <= 2) = 0.375Exercice · Classer avec des ex aequo
facileDonnez les rangs des notes de satisfaction suivantes : 4, 2, 5, 4, 3, 4, 1. Que devient le classement si l’on remplace chaque note par ?
Voir la solution
Trié : 1, 2, 3, 4, 4, 4, 5. Les trois « 4 » occupent les places 4, 5 et 6 : ils reçoivent chacun le rang moyen . Les rangs, dans l’ordre des données, sont donc 5, 2, 7, 5, 3, 5, 1.
La fonction est croissante sur les nombres positifs : l’ordre est conservé, donc les rangs sont exactement les mêmes. Tout test de rang donnera le même résultat sur les notes et sur leurs carrés.
En code
import numpy as npfrom scipy import stats
notes = np.array([4, 2, 5, 4, 3, 4, 1])print(stats.rankdata(notes)) # [5. 2. 7. 5. 3. 5. 1.]print(stats.rankdata(notes ** 2)) # mêmes rangs : x -> x² est croissante sur les positifsnotes <- c(4, 2, 5, 4, 3, 4, 1)rank(notes) # 5 2 7 5 3 5 1rank(notes^2) # mêmes rangs : x -> x² est croissante sur les positifsExercice · Moyenne, médiane et valeur extrême
moyenUn site mesure cinq durées de session (en minutes) : 2, 3, 3, 4, 48.
- Calculez la moyenne et la médiane.
- Combien d’observations faut-il modifier, au minimum, pour rendre la moyenne arbitrairement grande ? Et la médiane ?
- Qu’en déduisez-vous pour le choix d’un indicateur de durée typique ?
Voir la solution
- Moyenne : minutes. Médiane : la 3e valeur triée, soit 3 minutes.
- Pour la moyenne, une seule observation suffit : en la faisant tendre vers l’infini, la moyenne suit. Pour la médiane de 5 valeurs, il faut en modifier trois (plus de la moitié) pour l’emmener où l’on veut. On dit que le point de rupture (breakdown point) de la moyenne est 0 %, et celui de la médiane 50 %.
- La moyenne de 12 minutes ne décrit aucune session réelle. Pour une durée « typique », la médiane est plus fidèle ; la moyenne reste utile si l’on s’intéresse au total (temps cumulé passé sur le site), mais il faut alors l’accompagner d’un intervalle de confiance robuste, par exemple par bootstrap (chapitre 7).
En code
import numpy as np
sessions = np.array([2, 3, 3, 4, 48])print(sessions.mean(), np.median(sessions)) # 12.0 3.0
# Une seule valeur modifiée suffit à emporter la moyenne...une = sessions.copy(); une[4] = 10**6print(une.mean(), np.median(une)) # 200002.4 3.0
# ... la médiane ne bouge qu'à partir de trois valeurs modifiéesdeux = sessions.copy(); deux[3:] = 10**6trois = sessions.copy(); trois[2:] = 10**6print(np.median(deux), np.median(trois)) # 3.0 1000000.0sessions <- c(2, 3, 3, 4, 48)mean(sessions); median(sessions) # 12 et 3
# Une seule valeur modifiée suffit à emporter la moyenne...une <- sessions; une[5] <- 1e6mean(une); median(une) # 200002.4 et 3
# ... la médiane ne bouge qu'à partir de trois valeurs modifiéesdeux <- sessions; deux[4:5] <- 1e6trois <- sessions; trois[3:5] <- 1e6median(deux); median(trois) # 3 et 1e+06