Comment coder le test t de l'étudiant à partir de zéro en Python
L’un des tests d’hypothèses statistiques les plus utilisés est peut-être le test t de Student.
Étant donné que vous utiliserez peut-être ce test vous-même un jour, il est important de bien comprendre son fonctionnement. En tant que développeur, cette compréhension est mieux obtenue en mettant en œuvre vous-même le test d’hypothèse à partir de zéro.
Dans ce didacticiel, vous découvrirez comment implémenter le test d’hypothèse statistique du test t de Student à partir de zéro en Python.
Après avoir terminé ce tutoriel, vous saurez :
- Le test t de Student indiquera s’il est probable qu’il y ait deux échantillons étant donné que les échantillons ont été tirés de la même population.
- Comment implémenter le test t de Student à partir de zéro pour deux échantillons indépendants.
- Comment implémenter le test t de Student apparié à partir de zéro pour deux échantillons dépendants.
Démarrez votre projet avec mon nouveau livre Statistics for Machine Learning, comprenant des tutoriels étape par étape et les fichiers code source Python pour tous. exemples.
Commençons.
Présentation du didacticiel
Ce didacticiel est divisé en trois parties : ils sont:
- Test t de Student
- Test t de Student pour échantillons indépendants
- Test t de Student pour les échantillons dépendants
Test t de Student
Le test t de Student est un test d’hypothèse statistique permettant de vérifier si deux échantillons devraient provenir de la même population.
Il doit son nom au pseudonyme « Étudiant » utilisé par William Gosset, qui a développé le test.
Le test fonctionne en vérifiant les moyennes de deux échantillons pour voir si elles sont significativement différentes l'une de l'autre. Pour ce faire, il calcule l’erreur type de la différence entre les moyennes, qui peut être interprétée pour déterminer la probabilité de la différence si les deux échantillons ont la même moyenne (l’hypothèse nulle).
La statistique t calculée par le test peut être interprétée en la comparant aux valeurs critiques de la distribution t. La valeur critique peut être calculée à l'aide des degrés de liberté et d'un niveau de signification avec la fonction de point de pourcentage (PPF).
Nous pouvons interpréter la valeur statistique dans un test bilatéral, ce qui signifie que si nous rejetons l’hypothèse nulle, cela pourrait être dû au fait que la première moyenne est inférieure ou supérieure à la seconde moyenne. Pour ce faire, nous pouvons calculer la valeur absolue de la statistique de test et la comparer à la valeur critique positive (à droite), comme suit :
- Si abs(t-statistic) <= valeur critique : acceptez l'hypothèse nulle selon laquelle les moyennes sont égales.
- Si abs(t-statistic) > valeur critique : rejetez l'hypothèse nulle selon laquelle les moyennes sont égales.
Nous pouvons également récupérer la probabilité cumulée d'observer la valeur absolue de la statistique t en utilisant la fonction de distribution cumulative (CDF) de la distribution t afin de calculer une valeur p. La valeur p peut ensuite être comparée à un niveau de signification choisi (alpha) tel que 0,05 pour déterminer si l'hypothèse nulle peut être rejetée :
- Si p > alpha : acceptez l'hypothèse nulle selon laquelle les moyennes sont égales.
- Si p <= alpha : rejetez l'hypothèse nulle selon laquelle les moyennes sont égales.
En travaillant avec les moyennes des échantillons, le test suppose que les deux échantillons ont été tirés d'une distribution gaussienne. Le test suppose également que les échantillons ont la même variance et la même taille, bien que des corrections soient apportées au test si ces hypothèses ne sont pas vérifiées. Par exemple, voir le test t de Welch.
Il existe deux versions principales du test t de Student :
- Échantillons indépendants. Le cas où les deux échantillons ne sont pas liés.
- Échantillons dépendants. Le cas où les échantillons sont liés, comme des mesures répétées sur la même population. Également appelé test apparié.
Les tests t de Student indépendants et dépendants sont disponibles en Python via les fonctions SciPy ttest_ind() et ttest_rel() respectivement.
Remarque : je recommande d'utiliser ces fonctions SciPy pour calculer le test t de Student pour vos applications, si elles conviennent. Les implémentations de la bibliothèque seront plus rapides et moins sujettes aux bugs. Je recommanderais uniquement de mettre en œuvre le test vous-même à des fins d'apprentissage ou dans le cas où vous avez besoin d'une version modifiée du test.
Nous utiliserons les fonctions SciPy pour confirmer les résultats de notre propre version des tests.
Notez, à titre de référence, que tous les calculs présentés dans ce didacticiel sont tirés directement du chapitre 9 « t Tests » dans « Statistics in Plain English », troisième édition, 2010. Je mentionne cela car vous pouvez voir les équations avec des formes différentes, selon le texte de référence que vous utilisez.
Test t de Student pour échantillons indépendants
Nous commencerons par la forme la plus courante du test t de Student : le cas où nous comparons les moyennes de deux échantillons indépendants.
Calcul
Le calcul de la statistique t pour deux échantillons indépendants est le suivant :
t = observed difference between sample means / standard error of the difference between the means
ou
t = (mean(X1) - mean(X2)) / sed
Où X1 et X2 sont les premier et deuxième échantillons de données et sed est l'erreur type de la différence entre les moyennes.
L'erreur type de la différence entre les moyennes peut être calculée comme suit :
sed = sqrt(se1^2 + se2^2)
Où se1 et se2 sont les erreurs standards pour les premier et deuxième ensembles de données.
L'erreur type d'un échantillon peut être calculée comme suit :
se = std / sqrt(n)
Où se est l'erreur type de l'échantillon, std est l'écart type de l'échantillon et n est le nombre d'observations dans l'échantillon.
Ces calculs font les hypothèses suivantes :
- Les échantillons sont tirés d'une distribution gaussienne.
- La taille de chaque échantillon est à peu près égale.
- Les échantillons ont la même variance.
Mise en œuvre
Nous pouvons facilement implémenter ces équations en utilisant les fonctions de la bibliothèque standard Python, NumPy et SciPy.
Supposons que nos deux échantillons de données soient stockés dans les variables data1 et data2.
Nous pouvons commencer par calculer la moyenne de ces échantillons comme suit :
# calculate means
mean1, mean2 = mean(data1), mean(data2)
Nous sommes à mi-chemin.
Nous devons maintenant calculer l'erreur type.
Nous pouvons le faire manuellement, d’abord en calculant les écarts types de l’échantillon :
# calculate sample standard deviations
std1, std2 = std(data1, ddof=1), std(data2, ddof=1)
Et puis les erreurs standards :
# calculate standard errors
n1, n2 = len(data1), len(data2)
se1, se2 = std1/sqrt(n1), std2/sqrt(n2)
Alternativement, nous pouvons utiliser la fonction sem() SciPy pour calculer directement l'erreur standard.
# calculate standard errors
se1, se2 = sem(data1), sem(data2)
Nous pouvons utiliser les erreurs types des échantillons pour calculer l'« erreur type sur la différence entre les échantillons » :
# standard error on the difference between the samples
sed = sqrt(se1**2.0 + se2**2.0)
Nous pouvons maintenant calculer la statistique t :
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
Nous pouvons également calculer d’autres valeurs pour aider à interpréter et à présenter la statistique.
Le nombre de degrés de liberté pour le test est calculé comme la somme des observations dans les deux échantillons, moins deux.
# degrees of freedom
df = n1 + n2 - 2
La valeur critique peut être calculée à l'aide de la fonction de point de pourcentage (PPF) pour un niveau de signification donné, tel que 0,05 (confiance de 95 %).
Cette fonction est disponible pour la distribution t dans SciPy, comme suit :
# calculate the critical value
alpha = 0.05
cv = t.ppf(1.0 - alpha, df)
La valeur p peut être calculée à l'aide de la fonction de distribution cumulative sur la distribution t, toujours dans SciPy.
# calculate the p-value
p = (1 - t.cdf(abs(t_stat), df)) * 2
Ici, nous supposons une distribution bilatérale, dans laquelle le rejet de l’hypothèse nulle pourrait être interprétée comme si la première moyenne est soit plus petite, soit plus grande que la seconde.
Nous pouvons relier tous ces éléments dans une fonction simple permettant de calculer le test t pour deux échantillons indépendants :
# function for calculating the t-test for two independent samples
def independent_ttest(data1, data2, alpha):
# calculate means
mean1, mean2 = mean(data1), mean(data2)
# calculate standard errors
se1, se2 = sem(data1), sem(data2)
# standard error on the difference between the samples
sed = sqrt(se1**2.0 + se2**2.0)
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
# degrees of freedom
df = len(data1) + len(data2) - 2
# calculate the critical value
cv = t.ppf(1.0 - alpha, df)
# calculate the p-value
p = (1.0 - t.cdf(abs(t_stat), df)) * 2.0
# return everything
return t_stat, df, cv, p
Exemple travaillé
Dans cette section, nous calculerons le test t sur certains échantillons de données synthétiques.
Tout d’abord, générons deux échantillons de 100 nombres aléatoires gaussiens avec la même variance de 5 et des moyennes différentes de 50 et 51 respectivement. Nous nous attendons à ce que le test rejette l’hypothèse nulle et trouve une différence significative entre les échantillons :
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
Nous pouvons calculer le test t sur ces échantillons en utilisant la fonction SciPy intégrée ttest_ind(). Cela nous donnera une valeur statistique t et une valeur p à comparer, pour garantir que nous avons correctement implémenté le test.
L’exemple complet est répertorié ci-dessous.
# Student's t-test for independent samples
from numpy.random import seed
from numpy.random import randn
from scipy.stats import ttest_ind
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
# compare samples
stat, p = ttest_ind(data1, data2)
print('t=%.3f, p=%.3f' % (stat, p))
En exécutant l’exemple, nous pouvons voir une valeur statistique t et une valeur p.
Nous les utiliserons comme valeurs attendues pour le test sur ces données.
t=-2.262, p=0.025
Nous pouvons maintenant appliquer notre propre implémentation sur les mêmes données, en utilisant la fonction définie dans la section précédente.
La fonction renverra une valeur statistique t et une valeur critique. Nous pouvons utiliser la valeur critique pour interpréter la statistique t afin de voir si le résultat du test est significatif et si les moyennes sont effectivement différentes de celles attendues.
# interpret via critical value
if abs(t_stat) <= cv:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
La fonction renvoie également une valeur p. Nous pouvons interpréter la valeur p en utilisant un alpha, tel que 0,05, pour déterminer si le résultat du test est significatif et si les moyennes sont effectivement différentes de celles attendues.
# interpret via p-value
if p > alpha:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
Nous espérons que les deux interprétations concorderont toujours.
L’exemple complet est répertorié ci-dessous.
# t-test for independent samples
from math import sqrt
from numpy.random import seed
from numpy.random import randn
from numpy import mean
from scipy.stats import sem
from scipy.stats import t
# function for calculating the t-test for two independent samples
def independent_ttest(data1, data2, alpha):
# calculate means
mean1, mean2 = mean(data1), mean(data2)
# calculate standard errors
se1, se2 = sem(data1), sem(data2)
# standard error on the difference between the samples
sed = sqrt(se1**2.0 + se2**2.0)
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
# degrees of freedom
df = len(data1) + len(data2) - 2
# calculate the critical value
cv = t.ppf(1.0 - alpha, df)
# calculate the p-value
p = (1.0 - t.cdf(abs(t_stat), df)) * 2.0
# return everything
return t_stat, df, cv, p
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
# calculate the t test
alpha = 0.05
t_stat, df, cv, p = independent_ttest(data1, data2, alpha)
print('t=%.3f, df=%d, cv=%.3f, p=%.3f' % (t_stat, df, cv, p))
# interpret via critical value
if abs(t_stat) <= cv:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
# interpret via p-value
if p > alpha:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
L’exécution de l’exemple calcule d’abord le test.
Les résultats du test sont imprimés, y compris la statistique t, les degrés de liberté, la valeur critique et la valeur p.
Nous pouvons voir que la statistique t et la valeur p correspondent aux sorties de la fonction SciPy. Le test semble être correctement mis en œuvre.
La statistique t et la valeur p sont ensuite utilisées pour interpréter les résultats du test. Nous constatons que, comme nous nous y attendions, il existe suffisamment de preuves pour rejeter l’hypothèse nulle, constatant que les moyennes de l’échantillon sont probablement différentes.
t=-2.262, df=198, cv=1.653, p=0.025
Reject the null hypothesis that the means are equal.
Reject the null hypothesis that the means are equal.
Test t de Student pour les échantillons dépendants
Nous pouvons maintenant examiner le cas du calcul du test t de Student pour des échantillons dépendants.
C'est le cas où nous collectons des observations sur un échantillon de la population, puis appliquons un traitement, puis collectons des observations sur le même échantillon.
Le résultat est deux échantillons de même taille où les observations de chaque échantillon sont liées ou appariées.
Le test t pour les échantillons dépendants est appelé test t de Student apparié.
Calcul
Le calcul du test t de Student apparié est similaire à celui des échantillons indépendants.
La principale différence réside dans le calcul du dénominateur.
t = (mean(X1) - mean(X2)) / sed
Où X1 et X2 sont les premier et deuxième échantillons de données et sed est l'erreur type de la différence entre les moyennes.
Ici, sed est calculé comme :
sed = sd / sqrt(n)
Où sd est l'écart type de la différence entre les moyennes de l'échantillon dépendant et n est le nombre total d'observations appariées (par exemple, la taille de chaque échantillon).
Le calcul de sd nécessite d'abord le calcul de la somme des carrés des différences entre les échantillons :
d1 = sum (X1[i] - X2[i])^2 for i in n
Cela nécessite également la somme des différences (non carrées) entre les échantillons :
d2 = sum (X1[i] - X2[i]) for i in n
On peut alors calculer sd comme :
sd = sqrt((d1 - (d2**2 / n)) / (n - 1))
C'est ça.
Mise en œuvre
Nous pouvons implémenter le calcul du test t de Student apparié directement en Python.
La première étape consiste à calculer la moyenne de chaque échantillon.
# calculate means
mean1, mean2 = mean(data1), mean(data2)
Ensuite, nous aurons besoin du nombre de paires (n). Nous l'utiliserons dans quelques calculs différents.
# number of paired samples
n = len(data1)
Ensuite, nous devons calculer la somme des carrés des différences entre les échantillons, ainsi que la somme des différences.
# sum squared difference between observations
d1 = sum([(data1[i]-data2[i])**2 for i in range(n)])
# sum difference between observations
d2 = sum([data1[i]-data2[i] for i in range(n)])
Nous pouvons maintenant calculer l’écart type de la différence entre les moyennes.
# standard deviation of the difference between means
sd = sqrt((d1 - (d2**2 / n)) / (n - 1))
Ceci est ensuite utilisé pour calculer l’erreur type de la différence entre les moyennes.
# standard error of the difference between the means
sed = sd / sqrt(n)
Enfin, nous avons tout ce dont nous avons besoin pour calculer la statistique t.
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
La seule autre différence clé entre cette implémentation et celle pour échantillons indépendants est le calcul du nombre de degrés de liberté.
# degrees of freedom
df = n - 1
Comme auparavant, nous pouvons lier tout cela dans une fonction réutilisable. La fonction prendra deux échantillons appariés et un niveau de signification (alpha) et calculera la statistique t, le nombre de degrés de liberté, la valeur critique et la valeur p.
La fonction complète est répertoriée ci-dessous.
# function for calculating the t-test for two dependent samples
def dependent_ttest(data1, data2, alpha):
# calculate means
mean1, mean2 = mean(data1), mean(data2)
# number of paired samples
n = len(data1)
# sum squared difference between observations
d1 = sum([(data1[i]-data2[i])**2 for i in range(n)])
# sum difference between observations
d2 = sum([data1[i]-data2[i] for i in range(n)])
# standard deviation of the difference between means
sd = sqrt((d1 - (d2**2 / n)) / (n - 1))
# standard error of the difference between the means
sed = sd / sqrt(n)
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
# degrees of freedom
df = n - 1
# calculate the critical value
cv = t.ppf(1.0 - alpha, df)
# calculate the p-value
p = (1.0 - t.cdf(abs(t_stat), df)) * 2.0
# return everything
return t_stat, df, cv, p
Exemple travaillé
Dans cette section, nous utiliserons le même ensemble de données dans l’exemple concret que pour le test t de Student indépendant.
Les échantillons de données ne sont pas appariés, mais nous prétendrons qu'ils le sont. Nous nous attendons à ce que le test rejette l'hypothèse nulle et trouve une différence significative entre les échantillons.
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
Comme précédemment, nous pouvons évaluer le problème de test avec la fonction SciPy pour calculer un test t apparié. Dans ce cas, la fonction ttest_rel().
L’exemple complet est répertorié ci-dessous.
# Paired Student's t-test
from numpy.random import seed
from numpy.random import randn
from scipy.stats import ttest_rel
# seed the random number generator
seed(1)
# generate two independent samples
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
# compare samples
stat, p = ttest_rel(data1, data2)
print('Statistics=%.3f, p=%.3f' % (stat, p))
L'exécution de l'exemple calcule et imprime la statistique t et la valeur p.
Nous utiliserons ces valeurs pour valider le calcul de notre propre fonction de test t appariée.
Statistics=-2.372, p=0.020
Nous pouvons maintenant tester notre propre implémentation du test t de Student apparié.
L'exemple complet, y compris la fonction développée et l'interprétation des résultats de la fonction, est répertorié ci-dessous.
# t-test for dependent samples
from math import sqrt
from numpy.random import seed
from numpy.random import randn
from numpy import mean
from scipy.stats import t
# function for calculating the t-test for two dependent samples
def dependent_ttest(data1, data2, alpha):
# calculate means
mean1, mean2 = mean(data1), mean(data2)
# number of paired samples
n = len(data1)
# sum squared difference between observations
d1 = sum([(data1[i]-data2[i])**2 for i in range(n)])
# sum difference between observations
d2 = sum([data1[i]-data2[i] for i in range(n)])
# standard deviation of the difference between means
sd = sqrt((d1 - (d2**2 / n)) / (n - 1))
# standard error of the difference between the means
sed = sd / sqrt(n)
# calculate the t statistic
t_stat = (mean1 - mean2) / sed
# degrees of freedom
df = n - 1
# calculate the critical value
cv = t.ppf(1.0 - alpha, df)
# calculate the p-value
p = (1.0 - t.cdf(abs(t_stat), df)) * 2.0
# return everything
return t_stat, df, cv, p
# seed the random number generator
seed(1)
# generate two independent samples (pretend they are dependent)
data1 = 5 * randn(100) + 50
data2 = 5 * randn(100) + 51
# calculate the t test
alpha = 0.05
t_stat, df, cv, p = dependent_ttest(data1, data2, alpha)
print('t=%.3f, df=%d, cv=%.3f, p=%.3f' % (t_stat, df, cv, p))
# interpret via critical value
if abs(t_stat) <= cv:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
# interpret via p-value
if p > alpha:
print('Accept null hypothesis that the means are equal.')
else:
print('Reject the null hypothesis that the means are equal.')
L’exécution de l’exemple calcule le test t apparié sur l’exemple de problème.
La statistique t et la valeur p calculées correspondent à ce que nous attendons de l'implémentation de la bibliothèque SciPy. Cela suggère que la mise en œuvre est correcte.
L'interprétation de la statistique du test t avec la valeur critique et de la valeur p avec le niveau de signification trouve toutes deux un résultat significatif, rejetant l'hypothèse nulle selon laquelle les moyennes sont égales.
t=-2.372, df=99, cv=1.660, p=0.020
Reject the null hypothesis that the means are equal.
Reject the null hypothesis that the means are equal.
Rallonges
Cette section répertorie quelques idées pour étendre le didacticiel que vous souhaiterez peut-être explorer.
- Appliquez chaque test à votre propre exemple de problème artificiel.
- Mettez à jour le test indépendant et ajoutez la correction pour les échantillons présentant des variances et des tailles d'échantillon différentes.
- Effectuez une revue de code de l'un des tests implémentés dans la bibliothèque SciPy et résumez les différences dans les détails d'implémentation.
Si vous explorez l’une de ces extensions, j’aimerais le savoir.
Lectures complémentaires
Cette section fournit plus de ressources sur le sujet si vous souhaitez approfondir.
Livres
- Statistiques en anglais simple, troisième édition, 2010.
API
- API scipy.stats.ttest_ind
- API scipy.stats.ttest_rel
- API scipy.stats.sem
- API scipy.stats.t
Articles
- Test t de Student sur Wikipédia
- Test T de Welch sur Wikipédia
Résumé
Dans ce didacticiel, vous avez découvert comment implémenter le test d’hypothèse statistique du test t de Student à partir de zéro en Python.
Concrètement, vous avez appris :
- Le test t de Student indiquera s’il est probable qu’il y ait deux échantillons étant donné que les échantillons ont été tirés de la même population.
- Comment implémenter le test t de Student à partir de zéro pour deux échantillons indépendants.
- Comment implémenter le test t de Student apparié à partir de zéro pour deux échantillons dépendants.
Avez-vous des questions ?
Posez vos questions dans les commentaires ci-dessous et je ferai de mon mieux pour y répondre.