R中的动态范围界定问题

R中的动态范围界定问题,r,eval,dynamic-scope,R,Eval,Dynamic Scope,我正在阅读Hadley的AdvancedR,并在此基础上测试以下代码 subset2=功能(df,条件){ 条件调用=评估(替代(条件),df) df[条件呼叫,] } df=数据帧(a=1:10,b=2:11) 条件=3 第2小节(df,a

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

subset2=功能(df,条件){
条件调用=评估(替代(条件),df)
df[条件呼叫,]
}
df=数据帧(a=1:10,b=2:11)
条件=3
第2小节(df,a<条件)
然后我得到了以下错误消息:

eval(替换(条件),df)中出错:找不到对象“a”

我读了下面的解释,但不太明白:

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

在我看来,虽然“eval(substitute(condition),df)”,但他们找不到的变量是condition,那么为什么找不到对象“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)
subset2=功能(df,条件){
条件调用=评估(替代(条件),df)
df[条件呼叫,]
}
df=数据帧(a=1:10,b=2:11)
y=3
第2小节(df,a
这个更精简的示例可能会让您更容易看到哈德利的示例中发生了什么。首先要注意的是符号
条件
在这里以四种不同的角色出现,我用编号的注释标记了每种角色

                              ## 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
##符号的作用`条件`

我想补充一些细节,以防有人无意中发现这个问题。有问题的路线是

condition_call = eval(substitute(condition),df )  
  • substitute()函数中的条件对象是一个promise对象,其表达式槽为“a
  • 然后eval()函数开始计算df环境中的“a<条件”。其目标是找到a条件

    • 成功地在df中找到了一个而这不是错误产生的地方
    • 然后R开始在df中搜索条件,但找不到它
    • 因此R进入subset2的执行环境,并在执行环境中查找条件
    • 它找到的变量实际上是前面提到的promise对象,其表达式slot为“a<条件”
    • 为了计算这个表达式,R必须再次找到a,现在它再也找不到a了,因为它已经通过了df环境这是真正产生错误的部分。
在这里总结一下问题:

  • R确实在df中找到了一次a
  • 当R尝试查找条件时,出现错误,然后R将promise对象条件而不是分配给外部的4作为参数并尝试对其求值
  • 然后R遇到了问题:
    • 它尝试计算“aa

对于我的第二个示例,R在执行环境中找不到y,然后在subset2()的调用环境中找到y作为4,没有生成错误。在这种情况下,y的名称与promise对象的条件不同,R不会尝试计算“a谢谢您的回答!你能再解释一下吗?在我自己的例子中,“a”可以在data.frame df中找到,df是R应该寻找的第一个环境,那么为什么R找不到“a”?@Jason好的,我已经添加了一个解释。这里(在哈德利的例子中)可能让您感到困惑的是,表达式
condition+a
实际上出现并在两个不同的位置求值。当它出现并在功能体内部进行计算时,会找到一个匹配符号
a
。但是当它作为参数
condition=
的提供值进行计算时,它会在
.GlobalEnv
中搜索符号,但在那里找不到匹配的符号
a
。希望对你有帮助。非常感谢你帮助我!你的例子很有启发性!我认为您和我的代码的共同点是,它们都引用了globaenv()中未定义的变量。有一件事我仍然不明白:为什么变量的名称在这里很重要?如果我将全局变量从“condition”更改为“y”,则没有错误。请参见已编辑的问题。非常感谢@Jason在第二个示例中,当执行
eval(substitute(condition),df)
时,在
df
中找到
a
,在全局环境中找到
y
(在
df
或参数列表中首次搜索后未找到)。在第一个示例中,当执行
eval(substitute(condition),df)
时,
a
位于
df
中,而
condition
位于提供的参数列表中。在提供的参数列表中,它的值是
condition=condition+a
。在计算该表达式时,
condition
a
都在全局环境中搜索,但只找到了
condition
。@JoshO'Brien我有一个关于eval的后续问题:如果您感兴趣。
condition_call = eval(substitute(condition),df )