Ich versuche, meinen eigenen Python-Code zu schreiben, um t-Statistiken und p-Werte für einen und zwei unabhängige t-Tests zu berechnen. Ich kann die normale Näherung verwenden, aber im Moment versuche ich nur die t-Verteilung zu verwenden. Es ist mir nicht gelungen, die Ergebnisse der SciPy-Statistikbibliothek mit meinen Testdaten abzugleichen. Ich könnte ein neues Paar Augen gebrauchen, um zu sehen, ob ich irgendwo einen dummen Fehler mache.
Beachten Sie, dass dies weniger eine Codierungsfrage ist als vielmehr eine Frage: "Warum liefert diese Berechnung nicht den richtigen t-stat?" Ich gebe den Code der Vollständigkeit halber an, erwarte aber keine Software-Beratung. Helfen Sie einfach zu verstehen, warum dies nicht richtig ist.
Mein 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
Aktualisieren:
Nachdem ich etwas mehr über den T-Test des Welch gelesen hatte, sah ich, dass ich die Welch-Satterthwaite-Formel verwenden sollte, um Freiheitsgrade zu berechnen. Ich habe den obigen Code aktualisiert, um dies widerzuspiegeln.
Mit den neuen Freiheitsgraden bekomme ich ein näheres Ergebnis. Mein zweiseitiger p-Wert ist gegenüber der SciPy-Version um etwa 0,008 niedriger ... aber dies ist immer noch ein viel zu großer Fehler, sodass ich immer noch etwas falsch machen muss (oder die SciPy-Verteilungsfunktionen sind sehr schlecht, aber es ist schwer zu glauben Sie sind nur auf 2 Dezimalstellen genau.
Zweites Update:
Während ich weiter versuchte, dachte ich, dass SciPys Version möglicherweise automatisch die normale Annäherung an die t-Verteilung berechnet, wenn die Freiheitsgrade hoch genug sind (ungefähr> 30). Also habe ich meinen Code stattdessen mit der Normalverteilung erneut ausgeführt, und die berechneten Ergebnisse sind tatsächlich weiter von SciPys entfernt als bei Verwendung der T-Verteilung.
numpy.var
. Die Version, die ich gesehen habe, scheint darauf hinzudeuten, dass die MLE-Schätzung standardmäßig anstelle der unvoreingenommenen Schätzung berechnet wird. Um die unvoreingenommene Schätzung zu erhalten, muss sie mit der Option aufgerufen werden ddof=1
. ( 2 ) Verwenden Sie für den oberen Schwanz- Wert die Symmetrie der Verteilung, dh, und ( 3 ) für den zweiseitigen Wert etwas Ähnliches : . t pone_tailed_p_value = st.t.cdf(-t_stat,df)
two_tailed_p_value = 2*st.t.cdf(-np.abs(t_stat),df)