R 中的动态范围问题



我正在阅读Hadley的AdvancedR,并正在此URL上测试以下代码

subset2 = function(df, condition){
condition_call = eval(substitute(condition),df )  
df[condition_call,]
}
df = data.frame(a = 1:10, b = 2:11)
condition = 3
subset2(df, a < condition)

然后我收到以下错误消息:

eval(替换(条件), df) 中的错误:找不到对象 'a'

我阅读了如下解释,但不太明白:

如果 eval() 在数据帧内找不到变量(它的第二个参数),它会在 subset2() 的环境中查找。这显然不是我们想要的,所以我们需要一些方法来告诉 eval() 如果它找不到数据框中的变量,在哪里查找。

在我看来,虽然"eval(substitute(condition),df )",他们找不到的变量是条件,那么为什么找不到对象"a"呢?

另一方面,为什么以下代码不会出错?

subset2 = function(df, condition){
condition_call = eval(substitute(condition),df )  
df[condition_call,]
}
df = data.frame(a = 1:10, b = 2:11)
y = 3
subset2(df, a < y)

这个更精简的例子可能会让你更容易看到 Hadley 的例子中发生了什么。首先要注意的是,符号condition在这里以四个不同的角色出现,每个角色我都用编号注释标记。

## Role of symbol `condition`
f <- function(condition) {    #1 -- formal argument
a <- 100
condition + a             #2 -- symbol bound to formal argument
}
condition <- 3                #3 -- symbol in global environment
f(condition = condition + a)  #4 -- supplied argument (on RHS)
## Error in f(condition = condition + a) (from #1) : object 'a' not found

要了解的另一件重要事情是,在调用函数的求值框架中搜索所提供参数中的符号(此处为#4condition = condition + a的右侧)。从 4.3.3 节 R 语言定义的参数计算:

关于函数参数的计算,需要了解的最重要的事情之一是,提供的参数和默认参数的处理方式不同。提供给函数的参数在调用函数的计算帧中计算。函数的默认参数在函数的评估帧中计算。

在上面的示例中,调用f()的评估框架是全局环境,.GlobalEnv

一步一步地走,这是当您致电(condition = condition + a)时会发生什么。在函数求值期间,R 会遇到函数体中的表达式condition + a(在#2处)。它搜索acondition的值,并找到一个局部分配的符号a。它发现符号condition绑定到名为condition的形式参数(在#1处)。在函数调用期间提供的形式参数的值为condition + a(在#4处)。

如 R 语言定义中所述,表达式condition + a中的符号值在调用函数的环境(此处为全局环境)中搜索。由于全局环境包含一个名为condition的变量(在#3处赋值),但没有名为a的变量,因此它无法计算表达式condition + a(在#4处),并且失败并显示您看到的错误。

我想添加一些细节,以防有人偶然发现这个问题。有问题的行是

condition_call = eval(substitute(condition),df )  
  • substitute() 函数中的条件对象是一个 promise 对象,它的表达式槽是"一个<条件",substitute(condition)>条件"。

  • 然后 eval() 函数开始评估 df 环境中的"<条件"。它的目标是找到>a条件

    • DF 中成功找到 a,这不是生成错误的地方
    • 然后 R 开始在 df 中搜索条件并且找不到它。
    • 所以 R 上升到 subset2 的执行环境,并在执行环境中查找条件。
    • 它找到的变量实际上是前面提到的 promise 对象,表达式槽作为"<条件"。>
    • 为了计算这个表达式,R 必须再次找到a,现在它找不到更多,因为它已经通过了 df 环境。这是真正产生错误的部分。

总结一下这里的问题:

  • R 确实在df 中找到了一次。
  • 当 R 尝试
  • 查找条件,然后 R 将 promise 对象条件而不是外部分配的4作为参数并尝试评估它时,就会出现此错误。
  • 然后 R 遇到了问题:
    • 它尝试评估"<条件",但在>

对于我的第二个示例,R 在执行环境中找不到 y,然后在 subset2() 的调用环境中找到 y 作为 4,不产生错误。在这种情况下,y 的名称与 promise 对象条件不同,R 不会尝试评估"a <y",也不会生成错误。>

相关内容

  • 没有找到相关文章

最新更新