您不应使用 lm(data$y ~ data$whatever) 之类的根本原因是它存储了对训练数据集中列的硬编码引用。不使用 Auto 数据集,我们以 R 自带的 mtcars 数据集为例。
让我们以错误的方式拟合模型:
m <- lm(mtcars$mpg ~ mtcars$wt)
执行此操作后,模型的terms 组件现在专门引用mtcars$mpg 和mtcars$wt,而不是变量mpg 和wt:
m$terms
# mtcars$mpg ~ mtcars$wt
# attr(,"variables")
# list(mtcars$mpg, mtcars$wt)
# attr(,"factors")
# mtcars$wt
# mtcars$mpg 0
# mtcars$wt 1
# ...
现在尝试使用这个模型进行预测:
predict(m, newdata=data.frame(wt=4))
# 1 2 3 4 5 6 7 8 9 10 11 12 13
# 23.282611 21.919770 24.885952 20.102650 18.900144 18.793255 18.205363 20.236262 20.450041 18.900144 18.900144 15.533127 17.350247
# 14 15 16 17 18 19 20 21 22 23 24 25 26
# 17.083024 9.226650 8.296712 8.718926 25.527289 28.653805 27.478021 24.111004 18.472586 18.926866 16.762355 16.735633 26.943574
# 27 28 29 30 31 32
# 25.847957 29.198941 20.343151 22.480940 18.205363 22.427495
# Warning message:
# 'newdata' had 1 row but variables found have 32 rows
发生了什么? predict 方法不是在寻找名为wt 的变量,而是在寻找名为mtcars$wt 的东西。在您的newdata 中没有任何此类内容,因此作为后备它在全局环境中查找(从技术上讲,它首先尝试在newdata 的环境中评估表达式mtcars$wt,然后在模型已拟合,即全局环境)。这成功了,实际上解析为我们用来拟合模型的原始数据列。因此,newdata 参数基本上被忽略了。
现在如果我们通过正确的方式拟合模型
m2 <- lm(mpg ~ wt, data=mtcars)
这会将变量名称mpg 和wt 存储在模型中,名称查找将按预期工作:
predict(m2, newdata=data.frame(wt=4))
# 1
# 15.90724