J'essaie d'écrire mon propre code Python pour calculer les statistiques t et les valeurs p pour des tests t indépendants à une et deux queues. Je peux utiliser l'approximation normale, mais pour le moment, j'essaie simplement d'utiliser la distribution t. Je n'ai pas réussi à faire correspondre les résultats de la bibliothèque de statistiques de SciPy sur mes données de test. Je pourrais utiliser une nouvelle paire d'yeux pour voir si je fais juste une erreur stupide quelque part.
Remarque, ce n'est pas tant une question de codage que c'est un "pourquoi ce calcul ne donne-t-il pas le bon t-stat?" Je donne le code pour l'exhaustivité, mais n'attendez aucun conseil logiciel. Aidez simplement à comprendre pourquoi ce n'est pas bien.
Mon code:
import numpy as np
import scipy.stats as st
def compute_t_stat(pop1,pop2):
num1 = pop1.shape[0]; num2 = pop2.shape[0];
# The formula for t-stat when population variances differ.
t_stat = (np.mean(pop1) - np.mean(pop2))/np.sqrt( np.var(pop1)/num1 + np.var(pop2)/num2 )
# ADDED: The Welch-Satterthwaite degrees of freedom.
df = ((np.var(pop1)/num1 + np.var(pop2)/num2)**(2.0))/( (np.var(pop1)/num1)**(2.0)/(num1-1) + (np.var(pop2)/num2)**(2.0)/(num2-1) )
# Am I computing this wrong?
# It should just come from the CDF like this, right?
# The extra parameter is the degrees of freedom.
one_tailed_p_value = 1.0 - st.t.cdf(t_stat,df)
two_tailed_p_value = 1.0 - ( st.t.cdf(np.abs(t_stat),df) - st.t.cdf(-np.abs(t_stat),df) )
# Computing with SciPy's built-ins
# My results don't match theirs.
t_ind, p_ind = st.ttest_ind(pop1, pop2)
return t_stat, one_tailed_p_value, two_tailed_p_value, t_ind, p_ind
Mise à jour:
Après avoir lu un peu plus sur le test t de Welch, j'ai vu que je devrais utiliser la formule de Welch-Satterthwaite pour calculer les degrés de liberté. J'ai mis à jour le code ci-dessus pour refléter cela.
Avec les nouveaux degrés de liberté, j'obtiens un résultat plus proche. Ma valeur p bilatérale est désactivée d'environ 0,008 par rapport à la version SciPy ... mais c'est toujours une erreur beaucoup trop importante donc je dois encore faire quelque chose de incorrect (ou les fonctions de distribution SciPy sont très mauvaises, mais c'est difficile à croire ils ne sont précis qu'à 2 décimales près).
Deuxième mise à jour:
Tout en continuant à essayer, je pensais que la version de SciPy calcule automatiquement l'approximation normale de la distribution t lorsque les degrés de liberté sont suffisamment élevés (environ> 30). J'ai donc réexécuté mon code en utilisant la distribution normale à la place, et les résultats calculés sont en fait plus éloignés de SciPy que lorsque j'utilise la distribution en t.
numpy.var
. La version que j'ai vue semble indiquer que l'estimation MLE est calculée par défaut au lieu de l'estimation non biaisée. Pour obtenir l'estimation impartiale, il faut l'appeler avec l'option ddof=1
. ( 2 ) Pour la queue supérieure -valeur, utiliser la symétrie de la -distribution, à savoir, et ( 3 ) pour les deux-tailed -valeur, faire quelque chose de similaire: . one_tailed_p_value = st.t.cdf(-t_stat,df)
two_tailed_p_value = 2*st.t.cdf(-np.abs(t_stat),df)