数学建模国赛倒计时4天——《统计模型精讲(混合效应模型R语言实现)》

文章目录

0、引言

本文基于 R语言 介绍完整实战案例。我们将使用内置数据集 sleepstudy,它记录了10名受试者在连续0-9天内的睡眠剥夺后,对反应时间(Reaction)的影响。这是一个典型的纵向数据(重复测量),非常适合用混合效应模型来分析。

这个案例会从数据探索 、模型构建 、模型比较 到结果可视化,逐步带你走一遍完整流程。


第一步:加载包和数据

首先,我们需要加载必要的R包并查看数据。

r 复制代码
# 安装必要的包(如果尚未安装)
# install.packages("lme4")
# install.packages("lmerTest")  # 提供p值
# install.packages("ggplot2")

# 加载包
library(lme4)      # 混合效应模型核心包
library(lmerTest)  # 提供p值
library(ggplot2)   # 绘图

# 加载内置数据集
data("sleepstudy")
head(sleepstudy)

输出示例:

复制代码
  Reaction Days Subject
1 249.5600    0     308
2 258.7047    1     308
3 250.8006    2     308
4 321.4398    3     308
5 356.8519    4     308
6 414.6901    5     308
  • Reaction:反应时间(毫秒),因变量(连续型)
  • Days:睡眠剥夺的天数(0-9天),自变量(连续型)
  • Subject:受试者编号(1-18),分组变量(分类)

第二步:数据可视化

我们先画一张图,直观地看看不同受试者的变化趋势。

r 复制代码
# 绘制每个受试者的反应时间随天数的变化
ggplot(sleepstudy, aes(x = Days, y = Reaction, color = Subject)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +  # 每个受试者单独拟合回归线
  theme_minimal() +
  labs(title = "不同受试者睡眠剥夺后的反应时间变化",
       x = "睡眠剥夺天数", y = "反应时间 (毫秒)")

从图中你会发现:

  • 大部分受试者的反应时间随天数增加而上升(正向斜率)。
  • 但不同受试者的**起点(截距)和上升速度(斜率)**差异很大。这就是引入随机效应的原因。

第三步:构建三个递进的混合效应模型

我们逐步从简单到复杂构建三个模型,并比较它们的优劣。

模型1:普通线性回归(无随机效应,作为基准)
r 复制代码
m0 <- lm(Reaction ~ Days, data = sleepstudy)
summary(m0)

This model assumes that all subjects share exactly the same intercept and slope, ignoring the "clustered" structure of the data.


模型2:随机截距模型(Random Intercept)

允许不同受试者的**起点(截距)不同,但斜率(Days的影响)**相同。

r 复制代码
m1 <- lmer(Reaction ~ Days + (1 | Subject), data = sleepstudy)
summary(m1)
  • (1 | Subject) 表示:随机效应只作用于截距,不同受试者的截距围绕总体平均值随机波动。

模型3:随机截距 + 随机斜率模型(最完整)

允许不同受试者既有不同的起点,又有不同的变化速度。

r 复制代码
m2 <- lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy)
summary(m2)
  • (1 + Days | Subject) 表示:截距和斜率都随受试者变化,且两者之间可能存在相关性。

第四步:模型比较与选择

我们可以用 anova() 进行似然比检验,比较哪个模型更好。

r 复制代码
# 比较模型1(m0)和模型2(m1)
# 注意:lm 和 lmer 不能直接比较,这里比较 m1 和 m2
anova(m1, m2)

输出示例:

t 复制代码
Data: sleepstudy
Models:
m1: Reaction ~ Days + (1 | Subject)
m2: Reaction ~ Days + (1 + Days | Subject)
    npar    AIC    BIC  logLik deviance  Chisq Df Pr(>Chisq)    
m1    4 1802.1 1814.8 -897.04   1794.1                         
m2    6 1763.9 1783.1 -875.97   1751.9 42.139  2  7.072e-10 ***

解读:

  • AIC和BIC值:m2(1763.9)明显小于m1(1802.1),说明m2拟合更好。
  • 似然比检验:p值极小(7.07e-10),表明随机斜率模型(m2)显著优于随机截距模型(m1)。这说明不同受试者受睡眠剥夺影响的程度确实不同。

因此,我们最终选择模型 m2作为最优模型。


第五步:查看模型结果并解释

r 复制代码
summary(m2)

关键输出解读:

固定效应部分:

r 复制代码
Fixed effects:
            Estimate Std. Error     df t value Pr(>|t|)    
(Intercept)  251.405      6.825  17.00  36.838  < 2e-16 ***
Days          10.467      1.546  17.00   6.771 2.68e-06 ***
  • 截距 (251.4):当Days=0时,受试者的平均反应时间约为251.4毫秒。
  • 斜率 (10.47):睡眠剥夺每增加1天,反应时间平均增加约10.47毫秒,且这个效应非常显著(p < 0.001)。

随机效应部分:

r 复制代码
Random effects:
 Groups   Name        Variance Std.Dev. Corr
 Subject  (Intercept) 612.10   24.741       
          Days         35.07    5.922   0.07
 Residual             654.94   25.592       
  • Subject截距方差 (612.10):不同受试者起点差异很大。
  • Days斜率方差 (35.07):不同受试者受睡眠剥夺影响的程度差异很大。
  • Corr = 0.07:截距和斜率的相关系数接近0,说明起点高的人不一定下降得慢。

第六步:可视化模型预测结果

最后,我们提取每个受试者的随机效应,并画出各自的拟合线,直观展示模型如何捕捉个体差异。

r 复制代码
>  coef(m1)
$Subject
    (Intercept)     Days
308    292.1888 10.46729
309    173.5556 10.46729
310    188.2965 10.46729
330    255.8115 10.46729
331    261.6213 10.46729
332    259.6263 10.46729
333    267.9056 10.46729
334    248.4081 10.46729
335    206.1230 10.46729
337    323.5878 10.46729
349    230.2089 10.46729
350    265.5165 10.46729
351    243.5429 10.46729
352    287.7835 10.46729
369    258.4415 10.46729
370    245.0424 10.46729
371    248.1108 10.46729
372    269.5209 10.46729

attr(,"class")
[1] "coef.mer"
r 复制代码
# 提取每个受试者的随机效应系数
coef_m1 <- coef(m1)$Subject
head(coef_m1)
coef(m1)
# 绘制原始数据 + 模型拟合线
ggplot(sleepstudy, aes(x = Days, y = Reaction, color = Subject)) +
  geom_point() +
  geom_abline(data = coef_m1, 
              aes(intercept = `(Intercept)`, slope = Days, color = rownames(coef_m1)),
              show.legend = FALSE) +
  theme_minimal() +
  labs(title = "混合效应模型(随机截距+斜率)拟合结果",
       x = "睡眠剥夺天数", y = "反应时间 (毫秒)")
r 复制代码
# 提取每个受试者的随机效应系数
coef_m2 <- coef(m2)$Subject
head(coef_m2)

# 绘制原始数据 + 模型拟合线
ggplot(sleepstudy, aes(x = Days, y = Reaction, color = Subject)) +
  geom_point() +
  geom_abline(data = coef_m2, 
              aes(intercept = `(Intercept)`, slope = Days, color = rownames(coef_m2)),
              show.legend = FALSE) +
  theme_minimal() +
  labs(title = "混合效应模型(随机截距+斜率)拟合结果",
       x = "睡眠剥夺天数", y = "反应时间 (毫秒)")
r 复制代码
> coef_m2
    (Intercept)       Days
308    253.6637 19.6662617
309    211.0064  1.8476053
310    212.4447  5.0184295
330    275.0957  5.6529356
331    273.6654  7.3973743
332    260.4447 10.1951090
333    268.2456 10.2436499
334    244.1725 11.5418676
335    251.0714 -0.2848792
337    286.2956 19.0955511
349    226.1949 11.6407181
350    238.3351 17.0815038
351    255.9830  7.4520239
352    272.2688 14.0032871
369    254.6806 11.3395008
370    225.7921 15.2897709
371    252.2122  9.4791297
372    263.7197 11.7513080
> 

你会看到:每个受试者都有一条属于自己的回归线,截距和斜率各不相同,完美地拟合了各自的个体差异。


总结与建议

模型 公式 适用场景
随机截距模型 `lmer(y ~ x + (1 group))`
随机截距+斜率 `lmer(y ~ x + (1 + x group))`

注意事项:

  1. 如果你的分组数很少(如 < 5),随机效应可能估计不准,需谨慎。
  2. 如果数据量较大,可以考虑 glmer() 用于广义混合效应模型(如逻辑回归、泊松回归)。
  3. 模型收敛问题:若遇到收敛警告,可尝试调整优化器参数或中心化自变量。

相关推荐
bkspiderx26 分钟前
Qt 的消息机制:事件驱动与信号槽的底层逻辑
开发语言·qt·信号槽·事件驱动·qt 的消息机制
晴天的雨.99228 分钟前
【C++算法】三数之和
开发语言·c++·算法
AC赳赳老秦37 分钟前
公开 CSV 数据集批量处理实战:用 OpenClaw 高效完成下载、清洗与标准化分析样本生成
java·开发语言·汇编·c++·python·deepseek·openclaw
j7~1 小时前
【Python】(篇七)《使用Python库》 -- 详解
开发语言·后端·python·编程学习·python标准库·python第三方库·python拓展
心中有你02141 小时前
C语言实现文件异或加密与RLE压缩算法
c语言·开发语言
小宋10211 小时前
MCP 工具也有供应链风险:注册中心、签名校验、版本锁定与白名单
开发语言·网络·人工智能·php
凉茶钱1 小时前
【C++】入门基础语法
开发语言·c++
个 人 练 习 生2 小时前
C++中的内存管理
开发语言·c++·经验分享·学习
jingli92 小时前
本地向量库索引把 C 盘塞爆 48.6G:一次 LanceDB 膨胀排查与根治实录
c语言·开发语言
言乐62 小时前
Python排名统计折线图
开发语言·python·django·virtualenv·pygame