短版
包含两个变量x
和y
的表达式,其中x
包含在环境1中
并且y
包含在第二个环境中。程序员如何评估
表达式?
详细版本
我有一个函数,它将formula
和data.frame作为参数。在
formula
的右侧是对函数splines::bs
的调用
生成B样条基础。主力函数做了一些事情,其中之一
这需要从公式中提取bs
调用并对其进行评估。该
我试图解决的问题涉及在参数时评估bs
调用
值包含在不同的环境中。
以下是重新创建我正在处理的问题所需的功能
library(splines)
extract_bmat <- function(form) {
B <- NULL
rr <- function(x) {
if (is.call(x) && grepl("bs", deparse(x[[1]]))) {
B <<- x
} else if (is.recursive(x)) {
as.call(lapply(as.list(x), rr))
} else {
x
}
}
z <- lapply(as.list(form), rr)
B
}
some_workhorse <- function(formula, data) {
# ... lots of cool stuff ...
# fit <- lm(formula, data)
bmat <- eval(extract_bmat(formula), data)
bmat
}
# The following works when evaluated in the .GlobalEnv
# The eval(extract_bmat(formula), data) call within the some_workhorse
# function works without errors
xi <- c(3, 4.5)
eg_data <- data.frame(x = 1:10, y = sin(1:10))
some_workhorse(y ~ bs(x, knots = xi), data = eg_data)
现在,如果函数some_workhorse
和xi
向量以及eg_data
在函数环境中生成data.frame
会导致错误。
foo <- function() {
xi_in_foo <- c(2, 3)
eg_data_in_foo <- data.frame(x = 1:10, y = sin(1:10))
some_workhorse(y ~ bs(x, knots = xi_in_foo), data = eg_data_in_foo)
}
foo()
# Error in sort(c(rep(Boundary.knots, ord), knots)) :
# object 'xi_in_foo' not found
错误的位置在splines::bs
调用范围内,但不是。{
重要部分;找不到xi_in_foo
是要解决的重要问题。
我知道这个问题与我在R.我的环境处理不当有关 主要问题是
eval(extract_bmat(formula), data)
写入some_workhorse
函数,以便在调用时正常工作
.GlobalEnv
或在函数环境中调用时?次要问题:
extract_bmat
函数中,我更愿意定义一个环境
对于B
并使用assign
而不是<<-
。我怀疑<<-
是最好的
选项因为递归水平的不确定性。
也就是说,我希望看到其他解决方案。感谢您的帮助。
答案 0 :(得分:2)
您应该将您的功能定义为
some_workhorse <- function(formula, data) {
# ... lots of cool stuff ...
# fit <- lm(formula, data)
bmat <- eval(extract_bmat(formula), data, environment(formula))
bmat
}
请注意,R中的formula
会捕获创建它们的环境。只要在定义公式的环境中存在xi_in_foo
,这应该可行。首先在data
list / data.frame中查找变量,然后将公式环境用作封闭环境。如果您没有使用公式,有时人们会使用parent.frame()
作为enclos=
参数,以便在调用函数的环境中查找变量,而不是将函数定义为R的词汇范围界定的默认值。