无法预测列表中的模型

Models in a list can't be predicted upon

考虑可以通过以下方式创建的模型列表:

fits = vector(mode="list",length=10)
for(i in 1:10)
{
  fits[[i]] = lm(nox~poly(dis,i),data=Boston)
}

其中,使用了 Boston 数据集,可以在 MASS 库中找到。
现在,为了做出预测:

dislim = range(Boston$dis) 
dis.grid = seq(from = dislim[1],to = dislim[2],by = 0.1)

这样做是为了给出 dis 的值,据此预测 nox 的值。 现在,为了进行预测,我们可以执行以下操作:

 predict(fits[[1]],list(dis = dis.grid))

但这会导致错误:

Error: variable 'poly(dis, i)' was fitted with type "nmatrix.1" but type "nmatrix.10" was supplied
In addition: Warning message:
In Z/rep(sqrt(norm2[-1L]), each = length(x)) :
  longer object length is not a multiple of shorter object length

但是,当我执行以下操作时:

lm.Boston = lm(nox~poly(dis,3),data=Boston)
lm.Boston.pred = predict(lm.Boston,list(dis = dis.grid))

它工作正常。那么,为什么我不能在列表的情况下这样做呢?

指定动态公式的正确方法是使用pasteas.formula

library(MASS)
data(Boston)

dislim <- range(Boston$dis) 
dis.grid <- seq(from = dislim[1],to = dislim[2],by = 0.1)

models <- lapply(1:10, function(i){
  form = as.formula(paste0("nox~", "poly(dis," , i, ")"))
  lm(form, data=Boston)
})

预测

lapply(models, function(x){
  predict(x, list(dis = dis.grid))
})

编辑:构建公式的另一种方法(根据 MrFlick 评论)是:

`lm(bquote(nox~poly(dis,.(i))), data=Boston)`

models1 <- lapply(1:10, function(i){
  lm(bquote(nox~poly(dis,.(i))), data=Boston)
})

另外(根据 Nathan Werth 的评论)如果公式:

models2 <- lapply(1:10, function(i){
    lm(nox~poly(dis,i),data=Boston)
})
使用

i 被视为模型中的变量,可以通过以下方式利用此类行为:

predict(models2[[1]], list(dis = dis.grid, i = 1)

library(purrr)
models <- lapply(1:10, function(i){
  form = as.formula(paste0("nox~", "poly(dis," , i, ")"))
  lm(form, data=Boston)
})

models1 <- lapply(1:10, function(i){
  lm(bquote(nox~poly(dis,.(i))), data=Boston)
})

models2 <- lapply(1:10, function(i){
  lm(nox~poly(dis,i),data=Boston)
})

missuse <- lapply(models, function(x){
  predict(x,list(dis = dis.grid))
})

MrFlick <- lapply(models1, function(x){
  predict(x,list(dis = dis.grid))
})

NathanWerth <- purrr::map2(models2, 1:10, function(x, y){
  predict(x,list(dis = dis.grid, i = y ))
})

purrr::pmap(list(missuse, MrFlick, NathanWerth), function(x, y, z) c(identical(x, y), identical(x, z)))