1つおよび2つのテールの独立したt検定のt統計とp値を計算するために、独自のPythonコードを記述しようとしています。通常の近似を使用できますが、現時点ではt分布のみを使用しようとしています。SciPyの統計ライブラリの結果をテストデータと照合することに失敗しました。私はどこかでばかげた間違いをしているかどうかを確認するために新鮮な目を使用することができました。
これは「なぜこの計算で正しいt統計が得られないのか」ということなので、これはコーディングの問題ではありません。完全を期すためにコードを提供しますが、ソフトウェアのアドバイスは期待していません。これが正しくない理由を理解するのに役立ちます。
私のコード:
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
更新:
ウェルチのt検定についてもう少し読んだ後、自由度を計算するためにウェルチ-サッターウェイト式を使用する必要があることがわかりました。これを反映するために上記のコードを更新しました。
新しい自由度により、より近い結果が得られます。私の両側のp値はSciPyバージョンのものから約0.008ずれています...しかし、これはまだ大きすぎるエラーなので、まだ何か間違っている必要があります(またはSciPy分布関数が非常に悪いですが、信じがたいです小数点以下2桁までしか正確ではありません)。
2回目の更新:
物事を試し続けている間に、自由度が十分に高い(およそ30より大きい)場合、SciPyのバージョンはt分布の法線近似を自動的に計算すると思いました。そこで、代わりに正規分布を使用してコードを再実行しました。計算結果は、t分布を使用する場合よりも実際にはSciPyの距離から離れています。
numpy.var
。私が見たバージョンは、MLE推定が不偏推定ではなくデフォルトで計算されることを示しているようです。公平な見積もりを取得するには、オプションでを呼び出す必要がありますddof=1
。(2)上側の値については、分布の対称性を使用します。つまり、(3)両側の値については、同様のことを行います。one_tailed_p_value = st.t.cdf(-t_stat,df)
two_tailed_p_value = 2*st.t.cdf(-np.abs(t_stat),df)