R编程:在多个环境中存在对象时评估表达式

时间:2015-10-24 21:38:19

标签: r

短版

包含两个变量xy的表达式,其中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_workhorsexi向量以及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而不是<<-。我怀疑<<-是最好的 选项因为递归水平的不确定性。 也就是说,我希望看到其他解决方案。

感谢您的帮助。

1 个答案:

答案 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的词汇范围界定的默认值。