微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

stats.ttest_ind() 与学生独立 t 检验的“手动”计算:不同的结果

如何解决stats.ttest_ind() 与学生独立 t 检验的“手动”计算:不同的结果

我正在比较 stats.ttest_ind() 与同一测试的“手动”计算,并得到不同的结果。

import numpy as np
import pandas as pd
import scipy.stats as stats
import math

stats.ttest_ind() 方法

#generate data
np.random.seed(123)
df = pd.DataFrame({ 
    'age':np.random.normal(40,5,200).round(),'sex':np.random.choice( ['male','female'],200,p=[0.4,0.6]),})

#define groups
men = df.age[df.sex == 'male']
women = df.age[df.sex == 'female']

#run t-test
test_stat,test_p = stats.ttest_ind(men,women)
print(test_stat,test_p)

出:

-0.9265613940505325 0.355282312357339

手动方法

#mean
men_mean,women_mean = men.mean(),women.mean()
#standard deviation
men_sd,women_sd = men.std(ddof=1),women.std(ddof=1)
#standard error
men_n,women_n = len(men),len(women)
men_se,women_se = men_sd/math.sqrt(men_n),women_sd/math.sqrt(women_n)
#standard error on the difference between men and women
se_diff = math.sqrt(men_se**2.0 + women_se**2.0)
#t-stat
t_stat = (men_mean - women_mean) / se_diff
#degrees of freedom
df = men_n + women_n - 2
#critical value
alpha = 0.05
cv = stats.t.ppf(1.0 - alpha,df)
# p-value
p = (1 - stats.t.cdf(abs(t_stat),df)) * 2
print(t_stat,cv,p)

出:

-0.9244538916746341 0.3563753194455255

我们可以看到存在细微差别。为什么?也许是因为 stats.ttest_ind() 如何计算自由度?非常感谢任何见解。

解决方法

以下有效。这是您上面的代码,只更改了两行。

import numpy as np
import pandas as pd
import scipy.stats as stats
import math
#generate data
np.random.seed(123)
df = pd.DataFrame({ 
    'age':np.random.normal(40,5,200).round(),'sex':np.random.choice( ['male','female'],200,p=[0.4,0.6]),})

#define groups
men = df.age[df.sex == 'male']
women = df.age[df.sex == 'female']

#run t-test
############################### CHANGED THE ROW BELOW HERE
test_stat,test_p = stats.ttest_ind(men,women,equal_var=False)  
print(test_stat,test_p)
#mean
men_mean,women_mean = men.mean(),women.mean()
#standard deviation
men_sd,women_sd = men.std(ddof=1),women.std(ddof=1)
#standard error
men_n,women_n = len(men),len(women)
men_se,women_se = men_sd/math.sqrt(men_n),women_sd/math.sqrt(women_n)
#standard error on the difference between men and women
se_diff = math.sqrt(men_se**2.0 + women_se**2.0)
#t-stat
t_stat = (men_mean - women_mean) / se_diff
#degrees of freedom
############################### CHANGED THE ROW BELOW HERE
df = (men_sd**2/men_n + women_sd**2/women_n)**2 / ( men_sd**4/men_n**2/(men_n-1)  + women_sd**4/women_n**2/(women_n-1)   )
#critical value
alpha = 0.05
cv = stats.t.ppf(1.0 - alpha,df)
# p-value
p = (1 - stats.t.cdf(abs(t_stat),df)) * 2
print(t_stat,cv,p)

它输出

-0.9244538916746341 0.356441636045986
-0.9244538916746341 1.6530443278019797 0.3564416360459859

代码不一致的原因是:

在行 test_stat,women) 上,您接受了通过等方差假设计算 t 检验的默认设置。所以 scipy.stats 给你的计算是一个纯等方差 t 检验。 scipy.stats.ttest_ind

的文档中对此进行了描述

在您自己的代码中,您通常遵循 Welch test:您分别计算了男性和女性的均值估计值及其标准误,并以这种方式计算了 t 统计量。

您确实在一个地方偏离了 Welch 测试:自由度计算。自由度应该与我在代码中输入的公式(并链接到上面)近似,但您使用了适用于 equal-variance assumptions 下的计算。

如果您想了解有关如何计算这些统计数据的更多详细信息,或者为什么按原样定义它们,或者为什么您的代码不是您所期望的,我建议您查看 https://stats.stackexchange.com/ 和 {{3} } 更适合统计问题,相比之下 https://datascience.stackexchange.com/ 更适合编程。这两个社区都精通 Python,所以他们应该能够很好地帮助您。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。