在函数内的lapply中调用更新,为什么它不起作用?

时间:2017-12-20 15:30:01

标签: r lapply lm

这是来自Error in calling `lm` in a `lapply` with `weights` argument的后续问题,但可能不是同一个问题(但仍然相关)。

这是一个可重复的例子:

dd <- data.frame(y = rnorm(100),
                 x1 = rnorm(100),
                 x2 = rnorm(100),
                 x3 = rnorm(100),
                 x4 = rnorm(100),
                 wg = runif(100,1,100))

ls.form <- list(
  formula(y~x1+x2),
  formula(y~x3+x4),
  formula(y~x1|x2|x3),
  formula(y~x1+x2+x3+x4)
)

我有一个带有不同参数的函数(1-一个子样本,2- weights参数的一个colname,3-一个要尝试的公式列表和4-要使用的data.frame

f1 <- function(samp, dat, forms, wgt){
  baselm <- lm(y~x1, data = dat[samp,], weights = dat[samp,wgt])
  lapply(forms, update, object = baselm)
}

如果我调用该函数,我会收到错误:

f1(1:66, dat = dd, forms = ls.form, wgt = "wg")
 Error in is.data.frame(data) : object 'dat' not found 

我真的不明白为什么它找不到dat对象,它应该是fonction环境的一部分。问题出在代码的update部分,好像从函数中删除了这一行,代码就可以了。

最后,将使用lapply

调用此函数
lapply(list(1:66, 33:99), f1, dat=dd, forms = ls.form, wgt="wg")

3 个答案:

答案 0 :(得分:3)

我认为你的问题是由lm使用的范围规则引起的,这些规则在r平方中非常坦白。

一个选项是使用do.call使其工作,但是当它取消输入以给出用于标准打印方法的调用时,会得到一些难看的输出。

f1 <- function(samp, dat, forms, wgt){
  baselm <- do.call(lm,list(formula=y~x1, data = dat[samp,], weights = dat[samp,wgt]))
  lapply(forms, update, object = baselm)
}

更好的方法是使用eval(substitute(...))构造,它提供您最初预期的输出:

f2 <- function(samp, dat, forms, wgt){
  baselm <- eval(substitute(lm(y~x1, data = dat[samp,], weights = dat[samp,wgt])))
  lapply(forms, update, object = baselm)
}

答案 1 :(得分:1)

此类范围问题在lm个对象中非常常见。您可以通过指定正确的评估环境来解决此问题:

f1 <- function(samp, dat, forms, wgt){
  baselm <- lm(y~x1, data = dat[samp,], weights = dat[samp,wgt])
  mods <- lapply(forms, update, object = baselm, evaluate = FALSE)
  e <- environment()
  lapply(mods, eval, envir = e)
}

f1(1:66, dat = dd, forms = ls.form, wgt = "wg")
#works

答案 2 :(得分:0)

接受的错误工作,但我继续挖掘并找到了这个旧的r-help问题(here),它提供了更多选项和解释。我想我会把它发布在这里以防其他人需要它。