Estoy intentando escribir mi propio código en Python para calcular las estadísticas t y los valores p para pruebas t independientes de una y dos colas. Puedo utilizar la aproximación normal, pero por el momento estoy tratando de utilizar sólo la distribución t. No he tenido éxito en hacer coincidir los resultados de la biblioteca de estadísticas de SciPy en mis datos de prueba. Me vendría bien un par de ojos frescos para ver si estoy cometiendo un error tonto en alguna parte.
Nota, esto no es tanto una pregunta de codificación como un "¿por qué este cálculo no está dando la t-stat correcta?" Doy el código para completar, pero no esperes ningún consejo de software. Sólo ayuda para entender por qué no es correcto.
Mi código:
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
Actualización:
Después de leer un poco más sobre la prueba t de Welch, vi que debería utilizar la fórmula Welch-Satterthwaite para calcular los grados de libertad. He actualizado el código anterior para reflejar esto.
Con los nuevos grados de libertad, obtengo un resultado más cercano. Mi valor p de dos caras se aleja aproximadamente 0,008 del de la versión de SciPy... pero sigue siendo un error demasiado grande, así que debo estar haciendo algo incorrecto (o las funciones de distribución de SciPy son muy malas, pero es difícil creer que sólo sean precisas con dos decimales).
Segunda actualización:
Mientras seguía probando cosas, pensé que tal vez la versión de SciPy calcula automáticamente la aproximación Normal a la distribución t cuando los grados de libertad son lo suficientemente altos (aproximadamente > 30). Así que volví a ejecutar mi código usando la distribución Normal en su lugar, y los resultados calculados están realmente más lejos de los de SciPy que cuando uso la distribución t.