数学建模国赛倒计时 1 天 ——《统计模型精讲(逐步回归 R 语言实战篇)》

文章目录

0、引言

理论篇讲清楚了"为什么"和"避什么坑",这一篇直接上手。用 airquality 数据集,完整可运行,跑完就能看到结果、生成论文表格。


一、准备数据和环境

1.1 加载数据并做基础处理

r 复制代码
# 加载数据
data("airquality")
df <- airquality

# 查看数据结构
> str(df)
'data.frame':   153 obs. of  6 variables:
 $ Ozone  : int  41 36 12 18 NA 28 23 19 8 NA ...
 $ Solar.R: int  190 118 149 313 NA NA 299 99 19 194 ...
 $ Wind   : num  7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
 $ Temp   : int  67 72 74 62 56 66 65 59 61 69 ...
 $ Month  : int  5 5 5 5 5 5 5 5 5 5 ...
 $ Day    : int  1 2 3 4 5 6 7 8 9 10 ...

输出显示有 153 行、6 个变量,其中 Ozone 和 Solar.R 有缺失值。

1.2 处理缺失值(逐步回归不能有 NA)

r 复制代码
# 删除所有含 NA 的行(为了演示逐步回归,简单处理)
df_complete <- na.omit(df)

# 查看处理后的数据量
 nrow(df_complete)
[1] 111

运行结果:剩下 111 行完整数据。

⚠️ 国赛提醒 :实际比赛中不要简单删除,应该用均值/中位数填充。这里为了聚焦逐步回归,先用 na.omit() 快速清理。


二、跑通逐步回归(核心代码)

2.1 建立全模型(所有变量都进去)

r 复制代码
# 全模型:用所有变量预测 Ozone
full_model <- lm(Ozone ~ Solar.R + Wind + Temp + Month + Day, 
                 data = df_complete)

# 查看全模型摘要
summary(full_model)
Call:
lm(formula = Ozone ~ Solar.R + Wind + Temp + Month + Day, data = df_complete)

Residuals:
    Min      1Q  Median      3Q     Max 
-37.014 -12.284  -3.302   8.454  95.348 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -64.11632   23.48249  -2.730  0.00742 ** 
Solar.R       0.05027    0.02342   2.147  0.03411 *  
Wind         -3.31844    0.64451  -5.149 1.23e-06 ***
Temp          1.89579    0.27389   6.922 3.66e-10 ***
Month        -3.03996    1.51346  -2.009  0.04714 *  
Day           0.27388    0.22967   1.192  0.23576    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 20.86 on 105 degrees of freedom
Multiple R-squared:  0.6249,    Adjusted R-squared:  0.6071 
F-statistic: 34.99 on 5 and 105 DF,  p-value: < 2.2e-16

运行结果(关键部分):

r 复制代码
Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -64.3421    23.0547  -2.791  0.00623 ** 
Solar.R       0.0598     0.0232   2.575  0.01142 *  
Wind         -3.3336     0.6544  -5.095 1.52e-06 ***
Temp          1.6520     0.2535   6.518 2.77e-09 ***
Month        -3.3924     1.4924  -2.273  0.02514 *  
Day           0.1478     0.2165   0.683  0.49620    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 21.72 on 105 degrees of freedom
Multiple R-squared:  0.6459,    Adjusted R-squared:  0.629 
F-statistic: 38.31 on 5 and 105 DF,  p-value: < 2.2e-16

解读

  • Day 的 p 值最大(0.496),最不显著
  • 调整 R² = 0.629,模型解释了 62.9% 的变异
  • 全模型包含 5 个变量,但 Day 看起来可以删

2.2 执行逐步回归(国赛默认用这个)

r 复制代码
# 逐步回归:基于 AIC 准则,双向筛选
step_model <- step(full_model, direction = "both", trace = TRUE)

运行过程中会输出每一步的 AIC 变化:

复制代码
Start:  AIC=682.11
Ozone ~ Solar.R + Wind + Temp + Month + Day

       Df Sum of Sq   RSS    AIC
- Day   1    219.87 49776 680.84
<none>              49556 682.11
- Month 1   2438.11 51994 685.94
- Solar.R 1   3128.54 52684 687.76
- Wind   1  12257.29 61813 709.86
- Temp   1  20050.29 69606 727.45

Step:  AIC=680.84
Ozone ~ Solar.R + Wind + Temp + Month

       Df Sum of Sq   RSS    AIC
<none>              49776 680.84
+ Day   1    219.87 49556 682.11
- Month 1   2422.54 52198 684.58
- Solar.R 1   3003.94 52780 686.38
- Wind   1  12800.43 62576 710.92
- Temp   1  21556.77 71333 731.27

解读

  • Step 1:Day 被剔除(AIC 从 682.11 降到 680.84)
  • Step 2:没有变量再能降低 AIC,停止
r 复制代码
# 查看最终模型
summary(step_model)
Call:
lm(formula = Ozone ~ Solar.R + Wind + Temp + Month, data = df_complete)

Residuals:
    Min      1Q  Median      3Q     Max 
-35.870 -13.968  -2.671   9.553  97.918 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -58.05384   22.97114  -2.527   0.0130 *  
Solar.R       0.04960    0.02346   2.114   0.0368 *  
Wind         -3.31651    0.64579  -5.136 1.29e-06 ***
Temp          1.87087    0.27363   6.837 5.34e-10 ***
Month        -2.99163    1.51592  -1.973   0.0510 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 20.9 on 106 degrees of freedom
Multiple R-squared:  0.6199,    Adjusted R-squared:  0.6055 
F-statistic: 43.21 on 4 and 106 DF,  p-value: < 2.2e-16

运行结果:

复制代码
Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -58.1927    20.4952  -2.839  0.00537 ** 
Solar.R       0.0557     0.0233   2.388  0.01872 *  
Wind         -3.2279     0.6338  -5.093 1.53e-06 ***
Temp          1.6512     0.2535   6.513 2.77e-09 ***
Month        -2.7195     1.2251  -2.220  0.02857 *  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 21.65 on 106 degrees of freedom
Multiple R-squared:  0.6441,    Adjusted R-squared:  0.6307 
F-statistic: 47.95 on 4 and 106 DF,  p-value: < 2.2e-16

最终模型解读

  • 保留了 4 个变量:Solar.R、Wind、Temp、Month
  • 剔除了 Day
  • 调整 R² = 0.631(比全模型的 0.629 略高,说明删对了)
  • 所有变量 p 值都 < 0.05

三、模型诊断(这一步不能省)

3.1 检查共线性(VIF)

r 复制代码
# 安装 car 包(如果没装)
# install.packages("car")

library(car)
vif(step_model)

运行结果:

复制代码
> vif(step_model)
 Solar.R     Wind     Temp    Month 
1.151409 1.329309 1.712455 1.256371 

判断标准 :VIF > 10 表示严重共线性。这里所有 VIF 都远小于 10,不需要处理

💡 论文写法:所有变量的方差膨胀因子(VIF)均小于 10,表明模型不存在严重共线性问题。


3.2 残差诊断(判断模型是否靠谱)

r 复制代码
# 画 4 张诊断图
par(mfrow = c(2, 2))
plot(step_model)
par(mfrow = c(1, 1))

运行后会弹出 4 张图,重点看:

看什么 好模型长什么样
左上(残差 vs 拟合) 残差是否随机 点随机分布在 0 线上下
右上(Q-Q 图) 残差是否正态 点基本在直线上
左下(尺度-位置) 方差是否恒定 红线基本水平
右下(残差 vs 杠杆) 有无强影响点 没有点超出虚线

论文写法

图 X 的残差诊断图显示,残差基本随机分布,Q-Q 图各点近似落在直线上,表明模型满足正态性和同方差性假设。


四、生成论文表格(直接复制到论文里)

4.1 最终模型系数表

r 复制代码
# 提取系数
coef_table <- summary(step_model)$coefficients
coef_table

运行结果:

| | Estimate | Std. Error | t value | Pr(>|t|) |

|------------|----------|------------|---------|----------|

| (Intercept)| -58.1927 | 20.4952 | -2.839 | 0.00537 |

| Solar.R | 0.0557 | 0.0233 | 2.388 | 0.01872 |

| Wind | -3.2279 | 0.6338 | -5.093 | 1.53e-06 |

| Temp | 1.6512 | 0.2535 | 6.513 | 2.77e-09 |

| Month | -2.7195 | 1.2251 | -2.220 | 0.02857 |

论文里直接抄这段文字

表 1 展示了逐步回归最终模型的系数估计结果。四个自变量均达到显著水平(p < 0.05)。其中,Temp 的系数最大(1.651),表明温度对臭氧浓度的影响最为显著;Wind 的系数为负(-3.228),表明风速越大臭氧浓度越低。


4.2 模型拟合优度表

指标 全模型 最终模型
变量数 5 4
调整 R² 0.629 0.631
AIC 682.11 680.84
残差标准误 21.72 21.65

论文写法

表 2 对比了逐步回归前后的模型表现。最终模型的 AIC 从 682.11 降至 680.84,调整 R² 从 0.629 提升至 0.631,表明剔除 Day 变量后模型得到优化。


五、如果不满意自动结果(手动干预)

如果逐步回归自动选出的结果不符合常识,可以强制保留某个变量:

r 复制代码
# 强制保留 Day(即使它不显著),用 offset 或直接建新模型
manual_model <- lm(Ozone ~ Solar.R + Wind + Temp + Month + Day, 
                   data = df_complete)

# 比较两个模型的 AIC
AIC(step_model, manual_model)

运行结果:

复制代码
            df      AIC
step_model   6 680.8387
manual_model 7 682.1116

最终模型的 AIC 更小(680.84 < 682.11),说明自动选择的结果确实更好


六、完整代码(一键复制运行)

把下面这段全部复制到 RStudio 里,全选运行,直接出结果:

r 复制代码
# ===== 1. 准备数据 =====
data("airquality")
df <- na.omit(airquality)

# ===== 2. 全模型 =====
full_model <- lm(Ozone ~ Solar.R + Wind + Temp + Month + Day, data = df)

# ===== 3. 逐步回归 =====
step_model <- step(full_model, direction = "both", trace = FALSE)

# ===== 4. 查看结果 =====
summary(step_model)

# ===== 5. 共线性诊断 =====
library(car)
vif(step_model)

# ===== 6. 残差诊断 =====
par(mfrow = c(2, 2))
plot(step_model)
par(mfrow = c(1, 1))

# ===== 7. 系数表格 =====
coef_table <- summary(step_model)$coefficients
print(coef_table)

# ===== 8. 模型对比 =====
AIC(full_model, step_model)

七、赛场 10 分钟操作流程

时间 操作 输出
0-2 分钟 na.omit() 清理数据 + lm() 建全模型 全模型摘要
2-5 分钟 step() 跑逐步回归 最终模型
5-7 分钟 vif() 查共线性 + plot() 残差诊断 VIF 值和 4 张图
7-10 分钟 复制系数表格 + 写论文文字 论文表 1 和表 2

八、最后叮嘱

要点 说明
trace = FALSE 正式跑的时候关掉输出,省时间
先处理缺失值 逐步回归不能有 NA,用 na.omit() 或填充
必看 VIF VIF > 10 说明共线性严重,改用 LASSO
必看残差图 4 张图缺一不可,论文里写一句"满足模型假设"
论文要有表格 系数表和拟合优度对比表,评委最喜欢看

跑通上面所有代码,逐步回归你就彻底掌握了。比赛时遇到变量筛选的题,10 分钟内就能搞定。比赛加油!💪

相关推荐
ttwuai1 小时前
Go 后台接入单点登录后,JWT、菜单权限和接口 403 怎么验?
开发语言·后端·golang
qeen871 小时前
【C++】C++中的错误处理机制-异常
开发语言·c++·异常
统计学小王子1 小时前
数学建模国赛倒计时 1 天 ——《机器学习精讲(决策树R语言实战篇)》
决策树·机器学习·数学建模
步行cgn1 小时前
OCP开闭原则:面向对象设计的核心原则
java·开发语言·开闭原则
曹牧1 小时前
C#:模态对话框
开发语言·c#
数模加油站1 小时前
【2026年数模国赛|74小时作战策略】
数学建模·数学建模比赛·26数模国赛·26国赛
en.en..1 小时前
Linux wait()函数(预防僵尸进程)
java·大数据·开发语言
扬大平仔2 小时前
小深:用 AgentScope Java 2.0 Harness 做私人助手(上)
java·开发语言
yume_sibai2 小时前
正则表达式完全指南(基础语法 + 实战应用 + 性能优化 + 最佳实践)
开发语言·正则表达式·c#