用于比较均值的 t 检验
使用 scipy.stats 运行单样本、独立双样本和配对 t 检验,并解读置信区间
用于比较均值的 t 检验 是 CoddyKit 上的免费 Pandas & NumPy Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Pandas & NumPy Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Pandas & NumPy Academy 课程共包含 4 节课。
什么是 t 检验
t 检验是一种假设检验,用于判断组间 mean 的差异是否具有统计显著性,还是很可能由随机因素造成。它会将观察到的差异与数据的变异性进行比较,并产生t 统计量和p 值。如果 p ≤ 0.05(传统显著性阈值),我们就拒绝 mean 相等这一零假设。常见的 t 检验有三种:单样本 t 检验、独立双样本 t 检验和配对 t 检验,分别适用于不同的实验设计。
单样本 t 检验
单样本 t 检验用于检验样本的 mean 是否与已知或假设的总体 mean存在显著差异。例如:“我们的平均配送时间是否显著不同于行业标准 3 天?”请使用 scipy.stats.ttest_1samp(data, popmean)。零假设为 H₀: mean = popmean。较小的 p 值会促使您拒绝 H₀,并得出样本 mean 不同于目标值的结论。
import numpy as np
from scipy import stats
np.random.seed(42)
# Delivery times in days (true mean is ~3.5, not 3)
delivery_times = np.random.normal(loc=3.5, scale=0.8, size=50)
# Test: is our mean significantly different from 3 days?
stat, p = stats.ttest_1samp(delivery_times, popmean=3.0)
print(f'Sample mean: {delivery_times.mean():.3f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Differs from 3?', 'Yes' if p < 0.05 else 'No')独立双样本 t 检验
独立双样本 t 检验用于比较两个相互独立组的均值。例如:“A/B 检验中的变体产生的平均收入是否高于对照组?”请使用 scipy.stats.ttest_ind(group_a, group_b)。equal_var 参数很重要:当两个组的方差可能不同时,请设置 equal_var=False(Welch t 检验);对于大多数真实数据,这是更稳妥的默认设置。
import numpy as np
from scipy import stats
np.random.seed(0)
# A/B test revenue per session
control = np.random.normal(loc=25.0, scale=8.0, size=80)
variant = np.random.normal(loc=28.0, scale=9.0, size=80)
# Welch's t-test (does not assume equal variances)
stat, p = stats.ttest_ind(control, variant, equal_var=False)
print(f'Control mean: {control.mean():.2f}')
print(f'Variant mean: {variant.mean():.2f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Significant difference?', 'Yes' if p < 0.05 else 'No')单尾检验与双尾检验
默认情况下,t 检验是双尾检验:它们检验均值是否朝任一方向存在差异(大于或小于)。如果您有方向性假设(“该变体会提高收入”),请使用 单尾检验,并通过 alternative 参数指定 'greater' 或 'less'。单尾检验在指定方向上具有更高的检验效力,但无法为另一个方向提供证据。请在查看数据之前确定方向,以避免 HARKing(在得知结果后提出假设)。
import numpy as np
from scipy import stats
np.random.seed(1)
control = np.random.normal(25, 8, 100)
variant = np.random.normal(27, 8, 100)
# Two-tailed (default): does mean differ at all?
stat, p_two = stats.ttest_ind(control, variant, equal_var=False,
alternative='two-sided')
# One-tailed: is variant > control?
stat, p_one = stats.ttest_ind(control, variant, equal_var=False,
alternative='less')
print(f'Two-tailed p: {p_two:.4f}')
print(f'One-tailed p (variant greater): {p_one:.4f}')配对 t 检验
当 A 组中的每个观测值在 B 组中都有一个自然对应值时,应使用配对 t 检验——例如,同一组受试者接受处理前后的测量值,或同一批商店在两个不同月份的测量值。配对可以控制受试者之间的变异,因此对于同一数据,它比独立 t 检验更有检验效力。请使用 scipy.stats.ttest_rel(before, after)。元素顺序必须匹配:before[i] 和 after[i] 必须来自同一位受试者。
import numpy as np
from scipy import stats
np.random.seed(5)
# Blood pressure before and after medication (paired)
before = np.random.normal(130, 10, 30)
after = before - np.random.normal(5, 3, 30) # Treatment reduces BP by ~5
stat, p = stats.ttest_rel(before, after)
print(f'Mean before: {before.mean():.2f}')
print(f'Mean after: {after.mean():.2f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Treatment effective?', 'Yes' if p < 0.05 else 'No')解读 t 统计量
t 统计量表示观测到的差异距离零点有多少个标准误。t 统计量为 2,意味着观测到的差异比零假设下的预期值高出 2 个标准误。对于大样本、α=0.05 的双尾检验,临界值约为 ±1.96,因此 |t| > 1.96 时有 p < 0.05。p 值会将 t 统计量转换为概率,使您无需查阅 t 分布表也能更容易地解读结果。
import numpy as np
from scipy import stats
# Demonstrate relationship between t-statistic and p-value
for t_val in [1.0, 1.96, 2.5, 3.0, 4.0]:
# degrees of freedom = large sample -> t ~ normal
p = 2 * stats.t.sf(abs(t_val), df=100) # two-tailed
print(f't = {t_val:4.2f} -> p = {p:.4f} '
f'({'significant' if p < 0.05 else 'not significant'})')均值差的置信区间
仅凭 p 值无法告诉您效应的大小。请始终计算均值差的置信区间。包含零的 95% CI 与 p > 0.05(不显著)相符;不包含零则意味着差异显著。CI 还可以告诉您效应大小是否具有实际意义——收入上具有统计显著性的 0.01 美元差异可能无关紧要,而 p=0.06 且差异为 50 美元的结果对业务而言仍可能很重要。
import numpy as np
from scipy import stats
np.random.seed(0)
control = np.random.normal(25, 8, 80)
variant = np.random.normal(28, 8, 80)
diff = variant.mean() - control.mean()
se = np.sqrt(control.var()/len(control) + variant.var()/len(variant))
df = len(control) + len(variant) - 2
t_crit = stats.t.ppf(0.975, df=df)
ci_low = diff - t_crit * se
ci_high = diff + t_crit * se
print(f'Mean difference: {diff:.2f}')
print(f'95% CI: [{ci_low:.2f}, {ci_high:.2f}]')
print('CI excludes zero:', ci_low > 0 or ci_high < 0)效应大小:Cohen's d
统计显著性取决于样本量——样本足够大时,即使微小的差异也会达到显著。Cohen's d衡量实际显著性(效应大小):即均值差除以合并标准差。参考标准为:d < 0.2 表示可忽略,0.2–0.5 表示小,0.5–0.8 表示中等,> 0.8 表示大。请始终将效应大小与 p 值一同报告——p 值显著但 d = 0.05,意味着差异确实存在,但在实际应用中可能并无太大意义。
import numpy as np
from scipy import stats
np.random.seed(0)
g1 = np.random.normal(25, 8, 200)
g2 = np.random.normal(28, 8, 200)
stat, p = stats.ttest_ind(g1, g2)
# Cohen's d
pooled_std = np.sqrt((g1.var() + g2.var()) / 2)
cohens_d = (g2.mean() - g1.mean()) / pooled_std
print(f'p-value: {p:.4f}')
print(f'Cohen\'s d: {cohens_d:.3f}')
if cohens_d < 0.2: print('Effect: negligible')
elif cohens_d < 0.5: print('Effect: small')
elif cohens_d < 0.8: print('Effect: medium')
else: print('Effect: large')t 检验的假设
独立 t 检验基于以下假设:(1) 独立性——每个组内的观测值彼此独立;(2) 正态性——每个组中的数据近似服从正态分布(通过 CLT,在 n > 30 时具有稳健性);(3) 对于 Student t 检验(equal_var=True),方差相等。Welch t 检验(equal_var=False)放宽了第 3 个假设,因此更受推荐。当小样本(< 30)严重违反正态性时,请改用 Mann-Whitney U 检验。
import numpy as np
from scipy import stats
np.random.seed(0)
g1 = np.random.normal(10, 2, 30)
g2 = np.random.normal(11, 5, 30) # Very different variance!
# Levene test for equal variances
stat_l, p_l = stats.levene(g1, g2)
print(f'Levene test p: {p_l:.4f}')
if p_l < 0.05:
print('Unequal variances -> use Welch\'s (equal_var=False)')
stat, p = stats.ttest_ind(g1, g2, equal_var=False)
else:
print('Equal variances OK -> Student\'s t-test')
stat, p = stats.ttest_ind(g1, g2, equal_var=True)
print(f'Result: t={stat:.3f}, p={p:.4f}')Pandas Series 上的 t 检验
在实际应用中,您要检验的数据通常位于 Pandas DataFrame 的某一列中。您可以直接将 Pandas Series 传递给 scipy.stats 函数——这些函数既能无缝处理 Series,也能处理 NumPy 数组。常见流程是:筛选 DataFrame 以获取每个组的 Series,运行 t 检验,然后将结果存储在汇总 DataFrame 中。这种模式可以通过循环扩展到检验许多列对或组。
import pandas as pd
import numpy as np
from scipy import stats
np.random.seed(0)
df = pd.DataFrame({
'group': ['A']*60 + ['B']*60,
'revenue': np.concatenate([
np.random.normal(100, 20, 60),
np.random.normal(110, 22, 60)
])
})
grp_a = df.loc[df['group'] == 'A', 'revenue']
grp_b = df.loc[df['group'] == 'B', 'revenue']
stat, p = stats.ttest_ind(grp_a, grp_b, equal_var=False)
print(f'A mean: {grp_a.mean():.2f}, B mean: {grp_b.mean():.2f}')
print(f'p-value: {p:.4f}')多重比较问题
同时运行许多 t 检验会增加假阳性的可能性。如果以 α=0.05 运行 20 次 t 检验,预计仅凭偶然因素就会出现 1 次假阳性。这就是多重比较问题。请应用 Bonferroni 校正:将 α 除以检验次数(p_threshold = 0.05 / n_tests)。如果希望在不过于保守的同时获得更高的检验效力,请使用 statsmodels 中提供的 Benjamini-Hochberg 假发现率(FDR)校正。在包含许多指标的 A/B 检验中,请始终针对多重比较进行校正。
import numpy as np
from scipy import stats
np.random.seed(0)
n_tests = 10
results = []
for i in range(n_tests):
g1 = np.random.normal(0, 1, 50)
g2 = np.random.normal(0.1, 1, 50) # Tiny true effect
_, p = stats.ttest_ind(g1, g2)
results.append(p)
print('p-values:', [round(p, 3) for p in results])
bonferroni_thresh = 0.05 / n_tests
print(f'Bonferroni threshold: {bonferroni_thresh}')
print('Significant after Bonferroni:', sum(p < bonferroni_thresh for p in results))快速检查
检验您对本课数据分析概念的理解。
课程回顾
本课中您学到了:ttest_1samp 将样本均值与参考值进行比较,ttest_ind(使用 equal_var=False 的 Welch 检验)比较两个独立组,而 ttest_rel 处理配对测量值。请始终将 Cohen's d 与 p 值一同报告,以区分统计显著性和实际显著性。接下来,我们将使用卡方检验来检验分类变量之间的关系。
用 AI 导师学习 Python — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 30
- 课程
- 120
常见问题解答
「用于比较均值的 t 检验」课时是免费的吗?
是的 — 「用于比较均值的 t 检验」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Pandas & NumPy Academy 课程的其余内容,请升级到 CoddyKit PRO。 Pandas & NumPy Academy 课程共包含 4 节课。
「用于比较均值的 t 检验」这节课中我会学到什么?
使用 scipy.stats 运行单样本、独立双样本和配对 t 检验,并解读置信区间 你通过在浏览器中直接运行的动手代码来练习 Pandas & NumPy Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Pandas & NumPy Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Pandas & NumPy Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「用于比较均值的 t 检验」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Pandas & NumPy Academy 课中编写并运行代码吗?
能。每节 Pandas & NumPy Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 描述性统计与正态性检验
- 用于比较均值的 t 检验
- 独立性的卡方检验
- ANOVA 与事后检验