Aller au contenu

Testez une moyenne, une variance ou une proportion

Au chapitre précédent, l’écart-type de la machine était connu. C’est rarement le cas : en pratique, on l’estime sur les mêmes données. Et l’on ne teste pas que des moyennes : la régularité d’une production (sa variance) ou une proportion (un taux de défaut, un taux de clic) comptent autant.

Ce chapitre passe en revue les tests usuels sur un seul échantillon. Bonne nouvelle : la démarche en six étapes ne change pas. Seuls la statistique de test et sa loi changent. Nous retrouvons les 10 paquets de café pesés au chapitre 4 : xˉ=250,3\bar x = 250{,}3 g et s~=1,392\tilde s = 1{,}392 g.

Tester une moyenne quand l’écart-type est inconnu : le test de Student

Section intitulée « Tester une moyenne quand l’écart-type est inconnu : le test de Student »

On suppose les masses i.i.d. de loi N(m,σ2)\mathcal{N}(m, \sigma^2), avec σ\sigma inconnu. On veut savoir si la machine est bien centrée : H0:m=250H_0 : m = 250 contre H1:m≠250H_1 : m \ne 250.

Par le théorème de Fisher (chapitre 4), en remplaçant σ\sigma par S~n\tilde S_n :

T0=n (Xˉn−m0)S~n∼Tn−1 sous H0T_0 = \frac{\sqrt{n}\,(\bar X_n - m_0)}{\tilde S_n} \sim \mathcal{T}_{n-1} \text{ sous } H_0

Les régions critiques au niveau α\alpha se lisent sur les quantiles de Student :

AlternativeOn rejette H0H_0 si
H1:m≠m0H_1 : m \ne m_0∣t0∣>tn−1;1−α/2\lvert t_0 \rvert > t_{n-1;1-\alpha/2}
H1:m<m0H_1 : m < m_0t0<−tn−1;1−αt_0 < -t_{n-1;1-\alpha}
H1:m>m0H_1 : m > m_0t0>tn−1;1−αt_0 > t_{n-1;1-\alpha}
−4−2024valeur de T₀0,00,10,20,30,4densitérejet si |t₀| > 2,262t₀ = 0,68p-valeur ≈ 0,51 :aire ambre des deux côtésloi de Studentà 9 ddl sous H₀
t₀ = 0,68 tombe en plein milieu de la cloche : la moitié des échantillons donneraient un écart au moins aussi grand si la machine était bien centrée (p ≈ 0,51).
cafe <- c(251.3, 248.7, 250.9, 252.4, 249.5, 250.2, 247.8, 251.7, 250.6, 249.9)
t.test(cafe, mu = 250) # bilatéral : t = 0.68, p = 0.51
t.test(cafe, mu = 250, alternative = "less") # unilatéral H1 : m < 250
from scipy import stats
cafe = [251.3, 248.7, 250.9, 252.4, 249.5, 250.2, 247.8, 251.7, 250.6, 249.9]
print(stats.ttest_1samp(cafe, popmean=250)) # statistic 0.68, pvalue 0.51
print(stats.ttest_1samp(cafe, popmean=250, alternative="less"))

La torréfaction exige une machine régulière : un écart-type d’au plus 1 g. On teste H0:σ2≤1H_0 : \sigma^2 \le 1 contre H1:σ2>1H_1 : \sigma^2 > 1.

La moyenne mm étant inconnue, on utilise encore le théorème de Fisher :

T0=(n−1) S~n2σ02∼χn−12 sous H0 (σ2=σ02)T_0 = \frac{(n-1)\,\tilde S_n^2}{\sigma_0^2} \sim \chi^2_{n-1} \text{ sous } H_0 \ (\sigma^2 = \sigma_0^2)

Pour l’alternative σ2>σ02\sigma^2 > \sigma_0^2, on rejette si t0>χn−1;1−α2t_0 > \chi^2_{n-1;1-\alpha} ; pour σ2<σ02\sigma^2 < \sigma_0^2, si t0<χn−1;α2t_0 < \chi^2_{n-1;\alpha} ; en bilatéral, si t0t_0 sort de [χn−1;α/22 ; χn−1;1−α/22][\chi^2_{n-1;\alpha/2} \ ;\ \chi^2_{n-1;1-\alpha/2}].

051015202530(n − 1) S̃² / σ₀²0,000,020,040,060,080,100,12densité du χ² à 9 ddl2,7019,0217,44 : dansl’intervalleIC bilatéral : 2,5 % de chaque côté051015202530(n − 1) S̃² / σ₀²16,9217,44 > 16,92 :rejettest unilatéral : 5 % à droite
Même statistique 17,44, deux questions différentes : le seuil unilatéral (16,92) est plus bas que la borne bilatérale (19,02), car tout le risque de 5 % est placé à droite.

Si la moyenne mm est connue, on n’a rien à estimer pour la centrer : on utilise Sn′2=1n∑(Xi−m)2S_n'^2 = \frac{1}{n}\sum (X_i - m)^2 et nSn′2/σ02∼χn2n S_n'^2/\sigma_0^2 \sim \chi^2_n, avec nn degrés de liberté au lieu de n−1n - 1.

Les tests asymptotiques : quand l’échantillon est grand

Section intitulée « Les tests asymptotiques : quand l’échantillon est grand »

Et si les données ne sont pas gaussiennes ? Pour de grands échantillons, le théorème central limite vient à la rescousse.

Si les XiX_i sont i.i.d. de loi quelconque, de variance finie, alors sous H0:m=m0H_0 : m = m_0 :

T0=n (Xˉn−m0)S~n→LN(0,1)T_0 = \frac{\sqrt{n}\,(\bar X_n - m_0)}{\tilde S_n} \xrightarrow{\mathcal{L}} \mathcal{N}(0, 1)

C’est la même statistique que celle de Student, mais on la compare aux quantiles de la loi normale. En pratique, on considère l’approximation correcte à partir de n≥30n \ge 30 environ (plus si la loi est très dissymétrique).

Soit X1,…,XnX_1, \dots, X_n i.i.d. de Bernoulli de paramètre pp (1 si l’étudiant vient à vélo). L’estimateur est la proportion observée p^=Xˉn\hat p = \bar X_n. Sous H0:p=p0H_0 : p = p_0, le TCL donne

T0=n (p^−p0)p0(1−p0)→LN(0,1)T_0 = \frac{\sqrt{n}\,(\hat p - p_0)}{\sqrt{p_0(1 - p_0)}} \xrightarrow{\mathcal{L}} \mathcal{N}(0, 1)

Remarquez que la variance sous la racine est calculée avec p0p_0, la valeur de H0H_0 : sous l’hypothèse nulle, on la connaît. On demande en général np0≥5n p_0 \ge 5 et n(1−p0)≥5n(1 - p_0) \ge 5 pour que l’approximation soit bonne.

0,220,240,260,280,300,320,340,360,38proportion observée p̂ sur 400 étudiants0,02,55,07,510,012,515,017,5densitéseuil à 5 % : 0,338p̂ = 136/400= 0,34p-valeur ≈ 0,040si H₀ : p = 0,30,p̂ ≈ N(0,30 ; 0,0229²)
Sur l'échelle de p̂ : si 30 % des étudiants venaient à vélo, observer 34 % ou plus sur 400 n'arriverait que 4 fois sur 100. Le seuil à 5 % (0,338) est franchi de justesse.
prop.test(136, 400, p = 0.30, alternative = "greater", correct = FALSE) # X-squared = 1.75^2
binom.test(136, 400, p = 0.30, alternative = "greater") # test exact, sans TCL
import numpy as np
from scipy import stats
z0 = np.sqrt(400) * (0.34 - 0.30) / np.sqrt(0.30 * 0.70)
print(z0, stats.norm.sf(z0)) # 1.75 et 0.040
print(stats.binomtest(136, 400, p=0.30, alternative="greater")) # version exacte
ParamètreConditionsStatistique sous H0H_0Loi
Moyennegaussien, σ\sigma connun(Xˉ−m0)/σ\sqrt{n}(\bar X - m_0)/\sigmaN(0,1)\mathcal{N}(0,1) exacte
Moyennegaussien, σ\sigma inconnun(Xˉ−m0)/S~n\sqrt{n}(\bar X - m_0)/\tilde S_nTn−1\mathcal{T}_{n-1} exacte
Moyenneloi quelconque, nn grandn(Xˉ−m0)/S~n\sqrt{n}(\bar X - m_0)/\tilde S_nN(0,1)\mathcal{N}(0,1) approchée
Proportionnn grandn(p^−p0)/p0(1−p0)\sqrt{n}(\hat p - p_0)/\sqrt{p_0(1-p_0)}N(0,1)\mathcal{N}(0,1) approchée
Variancegaussien, mm connuenSn′2/σ02n S_n'^2/\sigma_0^2χn2\chi^2_n exacte
Variancegaussien, mm inconnue(n−1)S~n2/σ02(n-1)\tilde S_n^2/\sigma_0^2χn−12\chi^2_{n-1} exacte

Nos supports de cours s’arrêtent à la loi du chi-deux ; ses deux tests les plus célèbres sont un complément standard, que nous présentons ici et au chapitre suivant.

Le test de proportion compare une fréquence à une valeur théorique. Le test d’adéquation du chi-deux en compare plusieurs à la fois. On répartit les nn observations en kk classes ; OjO_j est l’effectif observé de la classe jj, et Ej=npjE_j = n p_j l’effectif attendu sous H0H_0 (où pjp_j est la probabilité de la classe jj selon la loi testée). La statistique est

D=∑j=1k(Oj−Ej)2Ej≈χk−1−r2 sous H0D = \sum_{j=1}^{k} \frac{(O_j - E_j)^2}{E_j} \approx \chi^2_{k - 1 - r} \text{ sous } H_0

où rr est le nombre de paramètres de la loi estimés sur les données (r=0r = 0 si la loi est entièrement spécifiée). On rejette H0H_0 si D>χk−1−r;1−α2D > \chi^2_{k-1-r;1-\alpha} : le test est toujours unilatéral à droite, car seuls les grands écarts sont suspects.

Pourquoi une loi du chi-deux ? Chaque terme ressemble au carré d’un écart centré réduit, qui est approximativement normal pour de grands effectifs. On retrouve une somme de carrés de normales, comme dans la définition du chapitre 4. La contrainte ∑Oj=n\sum O_j = n fait perdre un degré de liberté, et chaque paramètre estimé en fait perdre un autre.

123456face051015202530effectif observéattendu : 201,250,200,201,800,450,20en ambre : (Oⱼ − Eⱼ)² / Eⱼ, somme D = 4,105101520valeur de D0,0000,0250,0500,0750,1000,1250,1500,1750,200densitéD = 4,111,07χ² à 5 ddlsous H₀
La face 4 contribue le plus (1,80), mais la somme D = 4,1 reste au cœur de la loi du χ² à 5 ddl, bien avant le seuil 11,07 : rien de suspect.
chisq.test(c(15, 22, 18, 26, 17, 22), p = rep(1/6, 6)) # X-squared = 4.1, df = 5
from scipy import stats
print(stats.chisquare([15, 22, 18, 26, 17, 22])) # statistic 4.1, pvalue 0.54
  • Student : moyenne d’un échantillon gaussien, σ\sigma inconnu, n(Xˉ−m0)/S~n∼Tn−1\sqrt{n}(\bar X - m_0)/\tilde S_n \sim \mathcal{T}_{n-1}.
  • Chi-deux sur une variance : (n−1)S~n2/σ02∼χn−12(n-1)\tilde S_n^2/\sigma_0^2 \sim \chi^2_{n-1}, exact sous normalité mais très sensible à cette hypothèse.
  • Tests asymptotiques : pour nn grand, la même statistique qu’en Student, comparée à N(0,1)\mathcal{N}(0,1) ; pour une proportion, la variance vient de p0p_0.
  • Un test unilatéral et un intervalle bilatéral de même niveau peuvent donner des conclusions différentes : ils ne répondent pas à la même question.
  • Adéquation du chi-deux (complément) : ∑(Oj−Ej)2/Ej\sum (O_j - E_j)^2/E_j comparé à χk−1−r2\chi^2_{k-1-r}, avec des effectifs attendus d’au moins 5.

Exercice · Un test de Student à la main

facile

Un fournisseur garantit une teneur moyenne en sucre de 12 g pour 100 mL. Sur 16 bouteilles, supposées gaussiennes, on mesure xˉ=12,6\bar x = 12{,}6 g et s~=1,2\tilde s = 1{,}2 g. Testez au niveau 5 % si la teneur moyenne diffère de 12 g (t15;0,975≈2,131t_{15;0,975} \approx 2{,}131).

Voir la solution

H0:m=12H_0 : m = 12 contre H1:m≠12H_1 : m \ne 12. Sous H0H_0, T0=16(Xˉ−12)/S~∼T15T_0 = \sqrt{16}(\bar X - 12)/\tilde S \sim \mathcal{T}_{15}.

t0=4×0,6/1,2=2,0t_0 = 4 \times 0{,}6/1{,}2 = 2{,}0. Comme ∣t0∣=2,0<2,131\lvert t_0 \rvert = 2{,}0 < 2{,}131, on conserve H0H_0 au niveau 5 %. L’écart de 0,6 g n’est pas significatif avec 16 bouteilles (la p-valeur vaut environ 0,064). Cela ne prouve pas que la teneur vaut 12 g : l’échantillon est peut-être simplement trop petit.

En code

import numpy as np
from scipy import stats
n, moyenne, s, m0 = 16, 12.6, 1.2, 12
t0 = np.sqrt(n) * (moyenne - m0) / s
seuil = stats.t.ppf(0.975, df=n - 1)
print(t0, seuil) # 2.0 < 2.131 : on conserve H0
print(2 * stats.t.sf(abs(t0), df=n - 1)) # p-valeur : 0.064

Exercice · Taux de défaut d'une chaîne

moyen

Un contrat impose un taux de pièces défectueuses d’au plus 2 %. Sur 800 pièces contrôlées, on en trouve 24 défectueuses. Le contrat est-il respecté ? Testez au niveau 5 %, en vérifiant les conditions d’application.

Voir la solution

p^=24/800=0,03\hat p = 24/800 = 0{,}03. On veut montrer une violation du contrat : H0:p≤0,02H_0 : p \le 0{,}02 contre H1:p>0,02H_1 : p > 0{,}02.

Conditions : np0=16≥5n p_0 = 16 \ge 5 et n(1−p0)=784≥5n(1-p_0) = 784 \ge 5, l’approximation normale est acceptable.

t0=800 (0,03−0,02)0,02×0,98≈28,28×0,010,140≈2,02t_0 = \frac{\sqrt{800}\,(0{,}03 - 0{,}02)}{\sqrt{0{,}02 \times 0{,}98}} \approx \frac{28{,}28 \times 0{,}01}{0{,}140} \approx 2{,}02

Comme 2,02>z0,95=1,6452{,}02 > z_{0,95} = 1{,}645, on rejette H0H_0 : le taux de défaut dépasse significativement 2 % (p-valeur ≈0,022\approx 0{,}022).

En code

import numpy as np
from scipy import stats
n, defauts, p0 = 800, 24, 0.02
print(n * p0, n * (1 - p0)) # 16 et 784 : conditions remplies
p_hat = defauts / n
t0 = np.sqrt(n) * (p_hat - p0) / np.sqrt(p0 * (1 - p0))
print(t0, stats.norm.sf(t0)) # 2.02 et p = 0.022 : on rejette H0
print(stats.binomtest(defauts, n, p0, alternative="greater").pvalue) # test exact : 0.035

Exercice · Adéquation à une loi de Poisson

difficile

On compte le nombre d’accidents par semaine sur un carrefour pendant 100 semaines : 0 accident (40 semaines), 1 (35), 2 (18), 3 ou plus (7). On veut tester si le nombre d’accidents suit une loi de Poisson. Le paramètre, estimé par maximum de vraisemblance sur les relevés détaillés, vaut θ^=0,95\hat\theta = 0{,}95. Les probabilités de Poisson correspondantes sont 0,387 ; 0,367 ; 0,175 et 0,071 (la dernière regroupe « 3 ou plus »). Réalisez le test au niveau 5 %.

Voir la solution

Effectifs attendus : E=100×pE = 100 \times p, soit environ 38,67 ; 36,74 ; 17,45 et 7,13, tous supérieurs à 5.

D=(40−38,67)238,67+(35−36,74)236,74+(18−17,45)217,45+(7−7,13)27,13≈0,045+0,082+0,017+0,003≈0,15D = \frac{(40 - 38{,}67)^2}{38{,}67} + \frac{(35 - 36{,}74)^2}{36{,}74} + \frac{(18 - 17{,}45)^2}{17{,}45} + \frac{(7 - 7{,}13)^2}{7{,}13} \approx 0{,}045 + 0{,}082 + 0{,}017 + 0{,}003 \approx 0{,}15

Degrés de liberté : k−1−r=4−1−1=2k - 1 - r = 4 - 1 - 1 = 2, car on a estimé un paramètre (θ\theta). Le seuil vaut χ2;0,952≈5,99\chi^2_{2;0,95} \approx 5{,}99. On conserve H0H_0 : le modèle de Poisson est compatible avec les données.

En code

import numpy as np
from scipy import stats
observe = np.array([40, 35, 18, 7]) # 0, 1, 2, 3 ou plus
theta = 0.95
p = stats.poisson.pmf([0, 1, 2], theta)
p = np.append(p, 1 - p.sum()) # P(X >= 3)
attendu = 100 * p
print(attendu.round(2)) # [38.67 36.74 17.45 7.13]
# ddof=1 : un paramètre estimé, donc 4 - 1 - 1 = 2 degrés de liberté
D, p_valeur = stats.chisquare(observe, attendu, ddof=1)
print(D, p_valeur, stats.chi2.ppf(0.95, 2)) # 0.147 0.93 5.99 : on conserve H0