Estoy tratando de escribir mi propio código Python para calcular estadísticas t y valores p para pruebas t independientes de una y dos colas. Puedo usar la aproximación normal, pero por el momento estoy tratando de usar la distribución t. No pude hacer coincidir los resultados de la biblioteca de estadísticas de SciPy con mis datos de prueba. Podría usar un par de ojos nuevos para ver si estoy cometiendo un error tonto en alguna parte.
Tenga en cuenta que no se trata tanto de una pregunta de codificación como de "¿por qué este cálculo no produce el t-stat correcto?" Doy el código para completar, pero no espero ningún consejo de software. Solo ayuda a entender por qué esto no está bien.
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
Actualizar:
Después de leer un poco más sobre la prueba t de Welch, vi que debería usar la fórmula Welch-Satterthwaite para calcular los grados de libertad. Actualicé el código anterior para reflejar esto.
Con los nuevos grados de libertad, obtengo un resultado más cercano. Mi valor p de dos lados está desactivado en aproximadamente 0.008 de la versión de SciPy ... pero esto sigue siendo un error demasiado grande, así que todavía debo estar haciendo algo incorrecto (o las funciones de distribución de SciPy son muy malas, pero es difícil de creer solo tienen una precisión de 2 decimales).
Segunda actualización:
Mientras continuaba 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, y los resultados calculados en realidad están más lejos de SciPy's que cuando uso la distribución t.
numpy.var. La versión que vi parece indicar que la estimación MLE se calcula por defecto en lugar de la estimación imparcial. Para obtener la estimación imparcial, hay que llamarlo con el opcional ddof=1. ( 2 ) Para la cola superior -valor, utilice la simetría de la distribución t, es decir, y ( 3 ) para la de dos colas -valor, hacer algo similar: . one_tailed_p_value = st.t.cdf(-t_stat,df)two_tailed_p_value = 2*st.t.cdf(-np.abs(t_stat),df)