Aller au contenu

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é XX 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) :

F(x)=P(X≤x)F(x) = P(X \le x)

c’est-à-dire la probabilité que XX prenne une valeur inférieure ou égale à xx. Elle est croissante (au sens large), continue à droite, tend vers 0 en −∞-\infty et vers 1 en +∞+\infty.

Pour une variable discrète, on décrit la loi par sa fonction de masse (probability mass function, pmf) p(x)=P(X=x)p(x) = P(X = x). La fonction de répartition est alors en escalier : constante par morceaux, elle saute de p(x)p(x) en chaque valeur possible.

Avec une loi discrète, les bornes comptent. P(1<X≤2)=F(2)−F(1)=7/8−1/2=3/8P(1 < X \le 2) = F(2) - F(1) = 7/8 - 1/2 = 3/8, alors que P(1≤X≤2)=p(1)+p(2)=3/4P(1 \le X \le 2) = p(1) + p(2) = 3/4. Pour inclure la borne gauche, il faut retrancher la limite à gauche F(1−)=1/8F(1^-) = 1/8 au lieu de F(1)F(1).

0123nombre de « pile » x0,00,10,20,30,4p(x) = P(X = x)1/83/83/81/8fonction de masse0123x0,00,20,40,60,81,0F(x) = P(X ≤ x)1/81/27/81P(1 < X ≤ 2)= F(2) − F(1)= 3/8fonction de répartition en escalier
La fonction de répartition saute de p(x) en chaque valeur possible. Un point plein marque la valeur prise, un point creux la limite à gauche : c'est pour cela que P(1 < X ≤ 2) = F(2) − F(1) = 3/8 exclut la masse en 1.

Pour une variable continue, on utilise la densité (probability density function, pdf) f(x)=F′(x)f(x) = F'(x), et P(a<X<b)=F(b)−F(a)=∫abf(x) dxP(a < X < b) = F(b) - F(a) = \int_a^b f(x)\,dx. Ici, inclure ou non les bornes ne change rien, car P(X=a)=0P(X = a) = 0.

Le quantile d’ordre pp (avec 0<p<10 < p < 1) est la valeur xpx_p telle que F(xp)=pF(x_p) = p : une proportion pp de la loi se trouve en dessous. La médiane est x0,5x_{0,5}. Pour une loi discrète, où l’équation n’a pas toujours de solution, on prend xp=inf⁡{x:F(x)≥p}x_p = \inf \lbrace x : F(x) \ge p \rbrace.

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.375
print(X.cdf(2)) # P(X <= 2) = 0.875
Z = stats.norm() # loi normale centrée réduite
print(Z.pdf(0)) # densité en 0, environ 0.399
print(Z.ppf(0.05)) # quantile d'ordre 5 % (inverse de cdf), environ -1.645
print(Z.sf(1.96)) # fonction de survie 1 - F, environ 0.025
print(Z.isf(0.025)) # inverse de sf, environ 1.96

La méthode ppf (percent point function) est l’inverse de cdf, sf (survival function) vaut 1−F1 - F et isf est son inverse.

Beaucoup de lois usuelles appartiennent à une famille position-échelle (location-scale family) : leur densité s’écrit

f(x)=1b h ⁣(x−ab)f(x) = \frac{1}{b}\, h\!\left(\frac{x - a}{b}\right)

où hh est une densité de référence fixe, aa un paramètre de position (qui décale la courbe) et b>0b > 0 un paramètre d’échelle (qui l’étire). La loi normale en est l’exemple type, avec a=μa = \mu et b=σb = \sigma ; 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é ν\nu de la loi de Student en est un : pour ν=1\nu = 1, on obtient la loi de Cauchy, et quand ν→∞\nu \to \infty, on retrouve la loi normale. Plus ν\nu 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.

−505x0,00,10,20,30,40,5densitédensités246queues (échelle log)normaleStudent, ν = 3Cauchy (ν = 1)1101001 000taille de l’échantillon n−4−2024estimation du centreéchantillon de Cauchymoyennemédiane
Les trois densités se ressemblent au centre, mais les queues de Cauchy et de Student décroissent beaucoup plus lentement. Sur un échantillon de Cauchy, la médiane se stabilise vite autour de 0 alors que la moyenne fait des sauts imprévisibles, même après des milliers d'observations.

L’espérance se calcule par E(X)=∑xx p(x)E(X) = \sum_x x\,p(x) (cas discret) ou E(X)=∫xf(x) dxE(X) = \int x f(x)\,dx (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 ln⁡2≈0,693\ln 2 \approx 0{,}693 : la longue queue à droite tire la moyenne vers le haut.

024x0,00,20,40,60,81,0densitémédiane ln 2 ≈ 0,693espérance 1loi exponentielle de moyenne 11002005001 0002 000temps de chargement (ms, échelle log)médiane132 msmoyenne320,7 ms2 400 msles douze temps de chargement
Une longue queue à droite, ou une seule valeur extrême, tire la moyenne loin des observations typiques. La médiane reste au cœur des données.

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 μ\mu et σ\sigma), 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 :

SituationExemplePourquoi le paramétrique souffre
Petit échantillon8 patients, 6 plis de validation croiséeimpossible de vérifier la normalité, le théorème central limite ne joue pas encore
Loi asymétriquelatences, revenus, durées de sessionla moyenne et l’écart-type résument mal la loi
Valeurs aberrantesune mesure à 2 400 msune seule valeur déplace la moyenne et gonfle la variance
Données ordinalesnotes de satisfaction de 1 à 5l’é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 3/π≈0,9553/\pi \approx 0{,}955. 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 108/125=0,864108/125 = 0{,}864 pour une loi continue symétrique. L’assurance est donc peu chère.

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 nn.

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.

1234567891011121201301402 400//143 ms aurait reçule même rang 12valeurs (ms)rangs
Passer aux rangs, c'est ne garder que l'ordre : la distance de 2 400 ms au reste du groupe disparaît, la valeur extrême devient simplement « la 12e ».

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.

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 :

Valeur3,11,25,03,12,7
Rang3,5153,52

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 X(1)≤X(2)≤⋯≤X(n)X_{(1)} \le X_{(2)} \le \dots \le X_{(n)} 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) :

Fn(x)=1n∑i=1n1{Xi≤x}F_n(x) = \frac{1}{n} \sum_{i=1}^{n} \mathbf{1}\lbrace X_i \le x \rbrace

où 1{Xi≤x}\mathbf{1}\lbrace X_i \le x \rbrace vaut 1 si l’observation XiX_i est inférieure ou égale à xx, et 0 sinon. C’est simplement la proportion d’observations inférieures ou égales à xx : une fonction en escalier qui monte de 1/n1/n à chaque observation. Elle estime FF sans aucune hypothèse, et c’est la brique de base du test de Kolmogorov-Smirnov (chapitre 6) et du bootstrap (chapitre 7).

115120125130135140145150temps de chargement x (ms)0,000,250,500,751,00Fₙ(x)Fₙ(130) = 5/12dernier saut de 1/12à 2 400 ms, hors cadre
Fₙ monte de 1/12 à chaque observation. Cinq temps sur douze sont inférieurs ou égaux à 130 ms, donc Fₙ(130) = 5/12.
import numpy as np
from 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.0
print(stats.rankdata(lat)) # la valeur 2400 reçoit le rang 12
print(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.11
print(ecdf.cdf.evaluate(130)) # proportion des valeurs <= 130 : 5/12

En 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éfaut
Fn <- ecdf(lat)
Fn(130) # 5/12
  • Une loi est décrite par sa fonction de répartition F(x)=P(X≤x)F(x) = P(X \le x), 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 FF ; dans scipy.stats, ppf inverse cdf et isf inverse sf.
  • Les lois à queues lourdes (Student à faible ν\nu, 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 3/π3/\pi 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 FF sans hypothèse et sert de base à Kolmogorov-Smirnov et au bootstrap.

Exercice · Bornes et loi discrète

facile

XX suit la loi Binom(3,0,5)\mathrm{Binom}(3, 0{,}5). Calculez P(X≤1)P(X \le 1), P(X<1)P(X < 1), P(1≤X≤2)P(1 \le X \le 2) et P(1<X≤2)P(1 < X \le 2).

Voir la solution

Avec p=1/8, 3/8, 3/8, 1/8p = 1/8,\ 3/8,\ 3/8,\ 1/8 pour x=0,1,2,3x = 0, 1, 2, 3 :

  • P(X≤1)=F(1)=1/8+3/8=1/2P(X \le 1) = F(1) = 1/8 + 3/8 = 1/2 ;
  • P(X<1)=P(X=0)=1/8P(X < 1) = P(X = 0) = 1/8 (c’est la limite à gauche F(1−)F(1^-)) ;
  • P(1≤X≤2)=3/8+3/8=3/4P(1 \le X \le 2) = 3/8 + 3/8 = 3/4 ;
  • P(1<X≤2)=F(2)−F(1)=7/8−1/2=3/8P(1 < X \le 2) = F(2) - F(1) = 7/8 - 1/2 = 3/8.

Les deux derniers résultats diffèrent d’une masse p(1)=3/8p(1) = 3/8 : 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.5
print(X.cdf(0)) # P(X < 1) = P(X <= 0) = 0.125
print(X.pmf(1) + X.pmf(2)) # P(1 <= X <= 2) = 0.75
print(X.cdf(2) - X.cdf(1)) # P(1 < X <= 2) = 0.375

Exercice · Classer avec des ex aequo

facile

Donnez les rangs des notes de satisfaction suivantes : 4, 2, 5, 4, 3, 4, 1. Que devient le classement si l’on remplace chaque note xx par x2x^2 ?

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 (4+5+6)/3=5(4 + 5 + 6)/3 = 5. Les rangs, dans l’ordre des données, sont donc 5, 2, 7, 5, 3, 5, 1.

La fonction x↦x2x \mapsto x^2 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 np
from 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 positifs

Exercice · Moyenne, médiane et valeur extrême

moyen

Un site mesure cinq durées de session (en minutes) : 2, 3, 3, 4, 48.

  1. Calculez la moyenne et la médiane.
  2. Combien d’observations faut-il modifier, au minimum, pour rendre la moyenne arbitrairement grande ? Et la médiane ?
  3. Qu’en déduisez-vous pour le choix d’un indicateur de durée typique ?
Voir la solution
  1. Moyenne : (2+3+3+4+48)/5=60/5=12(2 + 3 + 3 + 4 + 48)/5 = 60/5 = 12 minutes. Médiane : la 3e valeur triée, soit 3 minutes.
  2. 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 %.
  3. 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**6
print(une.mean(), np.median(une)) # 200002.4 3.0
# ... la médiane ne bouge qu'à partir de trois valeurs modifiées
deux = sessions.copy(); deux[3:] = 10**6
trois = sessions.copy(); trois[2:] = 10**6
print(np.median(deux), np.median(trois)) # 3.0 1000000.0