在函数内的 lapply 内调用更新,为什么它不起作用?
Calling update within a lapply within a function, why isn't it working?
这是 的后续问题,但可能不是同一个问题(但仍然相关)。
这是一个可重现的例子:
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
参数的列名,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
对象,它应该是功能环境的一部分。问题出在代码的 update
部分,就像您从函数中删除这一行一样,代码仍然有效。
最后,这个函数会被调用 lapply
lapply(list(1:66, 33:99), f1, dat=dd, forms = ls.form, wgt="wg")
此类范围问题在 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
我认为你的问题是由于 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)
}
已接受的错误有效,但我继续挖掘并发现了这个旧的 r-help 问题 (here),它提供了更多选项和解释。我想我会 post 放在这里以防其他人需要它。
这是
这是一个可重现的例子:
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
参数的列名,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
对象,它应该是功能环境的一部分。问题出在代码的 update
部分,就像您从函数中删除这一行一样,代码仍然有效。
最后,这个函数会被调用 lapply
lapply(list(1:66, 33:99), f1, dat=dd, forms = ls.form, wgt="wg")
此类范围问题在 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
我认为你的问题是由于 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)
}
已接受的错误有效,但我继续挖掘并发现了这个旧的 r-help 问题 (here),它提供了更多选项和解释。我想我会 post 放在这里以防其他人需要它。