假设我们有一个函数调用stats::lm
,并将公式和数据帧作为参数。我们想要传递给stats::lm
的其他参数可以使用变量参数提供:
outer_function <- function(formula, data, ...) {
z <- stats::lm(formula = formula, data = data, ...)
return(z)
}
现在假设我们想要使用这个函数,并提供一个将传递给stats::lm
的附加参数(weights
(。
data <- data.frame(replicate(5, rnorm(100)))
weights <- replicate(100, 1)
formula <- X1 ~ X2 + X3
outer_function(formula = formula, data = data, weights = weights)
这在stats::lm
中产生以下错误:
Error in eval(extras, data, env) :
..1 used in an incorrect context, no ... to look in
调试对stats::lm
的调用时,我看到参数weights
正确地传递给了stats::lm
,但后来用于函数求值的match.call()
是
stats::lm(formula = formula, data = data, weights = ..1)
使得weights
被分配了...
-列表的第一个元素,该元素是空的。
有人能详细说明这种方法失败的原因吗?特别地,如果weights
是标量(比如5(,则不会出现问题,并且match.call()
将是
stats::lm(formula = formula, data = data, weights = 5)
目前,我正在为我的功能使用以下解决方案:
outer_function <- function(formula, data, ...) {
args <- list(formula = formula, data = data, ...)
z <- do.call(stats::lm, args)
return(z)
}
这是有效的,但我仍然想知道在CCD_ 15中的自变量是向量或列表的情况下,是否没有办法绕过CCD_。
我想不出有什么解决方案能像do.call
那样安全简洁。我已经调试到lm
调用中,可以解释发生了什么。
在lm
的正文中,您可以找到语句
mf <- eval(mf, parent.frame())
在分配的右侧,mf
是呼叫
stats::model.frame(formula = formula, data = data, weights = ..1,
drop.unused.levels = TRUE)
parent.frame()
是outer_function
调用的帧(换言之outer_function
的评估环境(。CCD_ 23正在对CCD_ 25中的CCD_。由于S3调度,parent.frame()
中最终评估的是调用
stats::model.frame.default(formula = formula, data = data, weights = ..1,
drop.unused.levels = TRUE)
在model.frame.default
的正文中,您可以找到语句
extras <- eval(extras, data, env)
在该分配的右侧,extras
是调用
list(weights = ..1)
指定mf
中与model.frame.default
的形式参数...
匹配的参数(在本例中仅为weights
,因为model.frame.default
具有名为formula
、data
和drop.unused.levels
的形式参数(;data
是包含您的模拟数据的数据帧;CCD_ 38是您的全局环境。(env
在model.frame.default
的前面被定义为environment(formula)
,这确实是您的全局环境,因为这就是您定义formula
的地方。(
eval
正在以env
作为外壳来评估data
中的extras
。此处抛出一个错误,因为数据帧data
和全局环境env
不是..n
的有效上下文。符号..1
仅在以...
作为形式自变量的函数的帧中有效。
你可能已经从?lm
中推断出了这个问题,其中指出:
所有
weights
、subset
和offset
的评估方式与formula
中的变量相同,即首先在data
中,然后在formula
的环境中。
在outer_function
调用中为weights
给定常量值(即,而不是环境中绑定的变量的名称,not函数调用(时没有问题,因为在这种情况下,match.call
不会替换符号..n
。因此
outer_function(formula = formula, data = data, weights = 5)
有效(好吧,抛出了一个不同的错误(,但
weights <- 5
outer_function(formula = formula, data = data, weights = weights)
和
outer_function(formula = formula, data = data, weights = rep(1, 100))
不要。