You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

线性回归模型预测报错:mpg数据集无因子却出现因子新水平错误

错误原因分析

你遇到的这个报错其实很常见,核心问题出在分类变量的水平在训练集和测试集的分布不一致:

  • 虽然你用str(mpg)查看时,变量显示为字符型(chr),但当你调用lm()拟合线性回归模型时,R会自动把字符型自变量转换为因子变量来处理分类信息。
  • 你随机拆分训练集和测试集时,刚好测试集里出现了训练集从未见过的model水平(也就是报错里的land cruiser wagon 4wd)。模型在训练阶段根本不知道这个水平的存在,自然无法对它进行预测,于是抛出了错误。

你可以用这段代码验证这个差异:

# 查看训练集和测试集的model水平差异
train_models <- unique(mpg[train_ind, ]$model)
test_models <- unique(mpg[-train_ind, ]$model)
setdiff(test_models, train_models)  # 这会返回训练集没有的测试集model水平
解决方案

针对这个问题,有几种实用的解决思路:

1. 分层抽样确保分类变量水平全覆盖

拆分数据集时,按分类变量(比如model)进行分层抽样,保证每个分类水平都能在训练集和测试集里出现。用dplyr就能轻松实现:

library(dplyr)
set.seed(1)

# 按model分层,每个model抽取50%的样本作为训练集
train_ind <- mpg %>%
  group_by(model) %>%
  sample_frac(0.5) %>%
  ungroup() %>%
  pull(row_number())

lm_mod <- lm(displ ~ ., data = mpg[train_ind, ])
lm_pred <- predict(lm_mod, mpg[-train_ind, ])

2. 对齐训练集和测试集的因子水平

如果必须用随机抽样,可以在拟合模型前,手动将测试集的因子水平与训练集对齐,把训练集没有的水平转为NA:

set.seed(1)
train.ind <- sample(1:nrow(mpg), round(nrow(mpg)/2))

# 处理训练集:将字符型变量转为因子
train_data <- mpg[train.ind, ]
train_data <- train_data %>% mutate(across(where(is.character), as.factor))

# 处理测试集:对齐因子水平,训练集没有的水平设为NA
test_data <- mpg[-train.ind, ]
test_data <- test_data %>% 
  mutate(across(where(is.character), ~factor(., levels = levels(train_data[[cur_column()]]))))

# 拟合模型并预测
lm_mod <- lm(displ ~ ., data = train_data)
lm_pred <- predict(lm_mod, test_data)

这样测试集里的新水平会被转为NA,预测时不会报错(默认会忽略这些行,或者你可以设置na.action = na.pass保留NA结果)。

3. 简化高基数分类变量

model这类分类变量的水平非常多(mpg里有38种model),很容易出现拆分后水平缺失的问题。你可以考虑:

  • 去掉这类高基数变量,改用更粗粒度的分类(比如manufacturer)
  • 使用正则化模型(如glmnet)来处理高基数分类变量,避免传统线性回归的因子水平限制

内容的提问来源于stack exchange,提问作者Adrian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:56:25