我正在围绕lm
构建一个包装器来进行一些额外的计算。我希望包装器将...
传递给lm
,但我遇到了lm
的{{1}}参数问题。
weights
如果我用权重参数调用包装器,
LmWrapper <- function(df, fmla, ...) {
est <- lm(fmla, df, ...)
list(model = est)
}
R不知道在哪里寻找重量:
data(airquality)
LmWrapper(airquality, Ozone ~ Wind, weights = Temp)
Error in eval(expr, envir, enclos) :
..1 used in an incorrect context, no ... to look in
帮助页面显示
所有
lm
,weights
和subset
的评估方式与offset
中的变量相同,即formula
中的变量,然后是data
的环境。
但包装器似乎改变了一些东西。
我该如何解决这个问题?
上述错误的formula
如下所示:
traceback()
直接致电8: eval(expr, envir, enclos)
7: eval(extras, data, env)
6: model.frame.default(formula = fmla, data = df, weights = ..1,
drop.unused.levels = TRUE)
5: stats::model.frame(formula = fmla, data = df, weights = ..1,
drop.unused.levels = TRUE)
4: eval(expr, envir, enclos)
3: eval(mf, parent.frame())
2: lm(fmla, df, ...) at #2
1: LmWrapper(diamonds, price ~ carat, weights = depth)
,效果很好:
lm
答案 0 :(得分:2)
所以问题是lm
通常在参数数据中查找这些名称,但某种方式确定了问题。您可以通过查找列引用并手动传递它来解决此问题。
LmWrapper <- function(df, fmla, ...) {
# get names of stuff in ...
argNames = sapply(substitute(list(...))[-1L], deparse)
# look for identical names in df
m = match(names(df), argNames, 0L)
# store other arguments from ... in a list
args = list(eval(parse(text = argNames[-m])))
# name the list
names(args) = names(argNames[-m])
# store complete values in args, instead of just references to columns
# the unlist code is rather ugly, the goal is to create a list where every
# element is a column of interest
args[names(argNames)[m]] = unlist(apply(df[, as.logical(m), drop = FALSE],
2, list), recursive = FALSE)
# also put other stuff in there
args$formula = fmla
args$data = df
# do lm
est = do.call(lm, args)
list(model = est)
}
data(airquality)
airquality$subset = airquality$Solar.R > 200
LmWrapper(airquality, Ozone ~ Wind, weights = Temp, subset = subset,
method = 'qr')
上面的代码不是最漂亮的,但它适用于subset
和weights
。或者,您可以将weights
和subset
作为例外处理。
答案 1 :(得分:0)
感谢范德曼(Vandenman)的回答。我刚刚实现了两个共享的更改,以防其他人遇到此线程:
1)如果...中除了数据列之外没有参数,则上述代码在列表中创建一个NA元素,并引发警告-我在下面添加了一个条件来解决此问题。
2)上面代码返回的模型对象调用非常长,因为它包含每个权重等。如果您不关心使用update()
的能力,那么替换它可能会更有见地通过实际的函数调用来记录发生的情况,如下所述。
run_lm <- function(df, formula, ...) {
# get names of stuff in ...
argNames = sapply(substitute(list(...))[-1L], deparse)
# look for identical names in df
m = match(names(df), argNames, 0L)
# store other arguments from ... in a list, if any
dot_args <- eval(parse(text = argNames[-m]))
if (is.null(dot_args)) {args <- list()
} else {
args <- list(dot_args)
# name the list
names(args) = names(argNames[-m])
}
# store complete values in args, instead of just references to columns
# the unlist code is rather ugly, the goal is to create a list where every
# element is a column of interest
args[names(argNames)[m]] = unlist(apply(df[, as.logical(m), drop = FALSE],
2, list), recursive = FALSE)
# also put other stuff in there
args$formula = formula
args$data = df
# do lm
mod <- do.call(lm, args)
mod$call <- sys.call()
mod
}