我正在尝试编写自己的 Python 代码来计算一个和两个有尾独立 t 检验的 t 统计量和 p 值。我可以使用正态近似值,但目前我试图只使用 t 分布。我未能将 SciPy 统计库的结果与我的测试数据相匹配。我可以用一双新的眼睛来看看我是否只是在某个地方犯了一个愚蠢的错误。
请注意,这与其说是一个编码问题,不如说是一个“为什么这个计算不能产生正确的 t-stat?” 我给出完整的代码,但不要指望任何软件建议。只是帮助理解为什么这是不对的。
我的代码:
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
更新:
在阅读了更多关于 Welch t 检验的内容后,我看到我应该使用 Welch-Satterthwaite 公式来计算自由度。我更新了上面的代码以反映这一点。
有了新的自由度,我得到了更接近的结果。我的双边 p 值与 SciPy 版本相差约 0.008 ......但这仍然是一个太大的错误,所以我仍然必须做一些不正确的事情(或者 SciPy 分布函数非常糟糕,但很难相信它们只精确到小数点后 2 位)。
第二次更新:
在继续尝试的同时,我认为当自由度足够高(大约 > 30)时,SciPy 的版本可能会自动计算 t 分布的正态近似值。所以我改用正态分布重新运行我的代码,计算结果实际上比我使用 t 分布时更远离 SciPy。