文章目录

R 统计分析:t.test() 与 lm()

发布于 2026-04-04 09:12:17 · 浏览 4 次 · 评论 0 条

R 统计分析:t.test() 与 lm()

在 R 中比较两组数据的均值差异,最常用的方法是 t.test() 函数。但很多人不知道,线性模型函数 lm() 其实也能完成同样的任务,而且结果完全一致。掌握这两种方法的关系,能让你更灵活地处理统计问题。


理解 t 检验的本质

t 检验用于判断两个独立样本(或配对样本)的均值是否存在显著差异。R 中的 t.test() 默认执行的是双样本、方差不齐的 Welch t 检验

线性模型 lm(y ~ x) 在 x 是一个二分类因子时,本质上就是在估计两组之间的均值差,并进行假设检验。其 t 统计量和 p 值与 t.test() 完全等价。


步骤一:准备示例数据

创建一个包含两组数值的数据框:

# 设置随机种子确保结果可复现
set.seed(123)

# 生成两组数据:A 组 30 个观测,均值 5;B 组 30 个观测,均值 6
group_A <- rnorm(30, mean = 5, sd = 1.2)
group_B <- rnorm(30, mean = 6, sd = 1.2)

# 合并为长格式数据框(适合 lm)
data <- data.frame(
  value = c(group_A, group_B),
  group = factor(c(rep("A", 30), rep("B", 30)))
)

此时 data 包含两列:value(数值)和 group(因子,取值 "A" 或 "B")。


步骤二:用 t.test() 进行两样本 t 检验

运行标准的双样本 t 检验:

t_result <- t.test(value ~ group, data = data)
print(t_result)

输出中重点关注:

  • t = -3.12(t 统计量)
  • df = 57.8(自由度,注意不是整数,说明用了 Welch 校正)
  • p-value = 0.0028(双侧 p 值)
  • mean in group A = 4.93mean in group B = 5.89(两组均值)

这说明在 0.05 显著性水平下,两组均值差异显著。


步骤三:用 lm() 实现等价的 t 检验

拟合一个以 group 为预测变量的线性模型:

lm_result <- lm(value ~ group, data = data)
summary(lm_result)

查看输出中的系数表(Coefficients):

| | Estimate | Std. Error | t value | Pr(>|t|) |
| :------------- | -------: | ---------: | ------: | -------: |
| (Intercept) | 4.93 | 0.21 | 23.48 | <2e-16 |
| groupB | 0.96 | 0.31 | 3.12 | 0.0028 |

关键点:

  • (Intercept) 对应 group A 的均值(因为 A 是参考组)。
  • groupB 的系数(0.96)表示 B 组比 A 组高 0.96,即均值差。
  • groupB 的 t 值(3.12)和 p 值(0.0028)与 t.test() 完全一致(符号相反是因为 t.test 默认 A-B,而 lm 是 B-A)。

注意:lm() 默认使用方差齐性假设(即 pooled variance),而 t.test() 默认使用 Welch 校正(方差不齐)。要让两者完全等价,需在 t.test() 中设置 var.equal = TRUE


步骤四:强制方差齐性使结果完全一致

重新运行 t 检验并指定方差相等:

t_equal <- t.test(value ~ group, data = data, var.equal = TRUE)
print(t_equal)

此时输出:

  • t = -3.12
  • df = 58(整数,因为假设方差齐)
  • p-value = 0.0028

再看 lm() 的结果,其残差标准误基于合并方差计算,因此:

  • lm() 的 t 值 = 3.12
  • 自由度 = 60 - 2 = 58
  • p 值 = 0.0028

两者现在在数值上完全对应。


步骤五:理解背后的数学关系

x 是二分类因子(0/1 编码)时,线性模型:

$$ y_i = \beta_0 + \beta_1 x_i + \varepsilon_i $$

其中:

  • $\beta_0$ 是参照组(x=0)的均值
  • $\beta_1$ 是两组均值之差

t 检验的原假设 $H_0: \mu_1 = \mu_2$ 等价于 $H_0: \beta_1 = 0$。

在方差齐性假设下,lm() 对 $\beta_1$ 的 t 检验与经典 Student's t 检验完全等价。


何时用哪个?

场景 推荐函数 理由
快速比较两组均值 t.test() 语法简单,直接输出均值、置信区间
后续要做多组比较(如 ANOVA)或加入协变量 lm() 可无缝扩展到更复杂模型
需要统一建模框架(如报告回归系数) lm() 结果结构与其他回归一致
不确定方差是否齐性 t.test()(默认) 自动使用 Welch 校正,更稳健

扩展:配对 t 检验也能用 lm() 吗?

可以,但需要技巧。配对 t 检验本质是对差值做单样本 t 检验。

假设有前后测数据 prepost

# 方法1:直接用 t.test
t.test(post, pre, paired = TRUE)

# 方法2:用 lm 对差值建模
diff <- post - pre
lm(diff ~ 1)  # 拟合截距模型

lm(diff ~ 1) 的系数就是平均差值,其 t 检验与配对 t 检验一致。

但注意:不能直接用 lm(post ~ pre) 来替代配对 t 检验——那是回归,不是配对比较。


验证你的结果是否一致

编写一个验证脚本确保两种方法输出匹配:

# 提取 t.test 的 t 值和 p 值(方差齐)
tt <- t.test(value ~ group, data = data, var.equal = TRUE)
t_ttest <- tt$statistic
p_ttest <- tt$p.value

# 提取 lm 的对应值
lm_mod <- lm(value ~ group, data = data)
coefs <- summary(lm_mod)$coefficients
t_lm <- coefs["groupB", "t value"]
p_lm <- coefs["groupB", "Pr(>|t|)"]

# 比较(允许微小浮点误差)
all.equal(abs(t_ttest), abs(t_lm))  # 应返回 TRUE
all.equal(p_ttest, p_lm)           # 应返回 TRUE
```

如果返回 `TRUE`,说明你的实现正确。

---

## 处理因子参考水平

`lm()` 的结果依赖于因子的**参考水平**。默认按字母顺序,"A" 是参照组。

**改变**参考组以调整解释方向:

```r
# 将 "B" 设为参照组
data$group <- relevel(data$group, ref = "B")
lm_new <- lm(value ~ group, data = data)
summary(lm_new)

现在 (Intercept) 是 B 组均值,groupA 系数是 A - B 的差值,t 值符号会反转,但 p 值不变。

这在解释结果时非常有用,尤其当你想让“对照组”作为基准。


总结关键对应关系

  • t.test(..., var.equal = TRUE)均值差 = lm() 中非截距项的 Estimate
  • t.testt 统计量(绝对值) = lm() 系数表中的 t value
  • 两者 p 值 完全相同(在方差齐性假设下)
  • t.test自由度 = lm()残差自由度(n - 2)

掌握这种对应关系,你就能在简单检验和复杂模型之间自由切换,而不必重复学习两套逻辑。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文