我想知道R如何将环境与公式联系起来的一些细节,以及在不同情况下所述环境需要什么,特别是关于〜是否开启的公式中没有包含。
让我们说我有两个像字符串一样的公式,通常会以编程方式创建,但为了简单起见,我将只定义为文字:
$ formula_str_no_tilde <- "a + b"
$ formula_str_with_tilde <- "~ a + b"
我打算使用这些来从包含a和b列的数据框进一步创建模型矩阵。为此,我想将类似公式的字符串转换为合法的公式。这里有一些非常奇怪的不同行为:
$ formula_no_tilde <- as.formula(formula_str_no_tilde)
> Error in eval(expr, envir, enclos) : object 'a' not found
,同时:
$ formula_with_tilde <- as.formula(formula_str_with_tilde)
no error
检查as.formula的文档,有一个env参数用于将环境绑定到公式。这个论点默认绑定了全局环境,这使得我们对错误信息有了一定的了解,因为我们还没有得到一个&#39; a&#39;在我们的全球环境中。它确实接受了第二次调用as.formula的神秘感,因为我们处于相同的情况......
由于全球环境受到约束,人们可能会怀疑可能整个冒险都被误导了,我们将无法使用我们的formula_with_tilde来制作模型矩阵,因为全球环境已经存在界。尽管如此:
$ D <- data.frame('a'=c(1, 2, 3), 'b'=c(-1, 0, 1))
$ model.matrix(formula_with_tilde, D)
按照你天真的希望工作。可能这是model.matrix的一个特性,它为你重新环境......
所以这是我的问题:
并且为了完整性:
答案 0 :(得分:3)
如果你想要一个未评估的调用对象(这是波形符操作符返回的那种R语言对象),那么你可以使用call
:
call( '+',quote(a),quote(b))
#a + b
您需要阻止解释器的默认操作,通过围绕quote
来评估第二个和第三个参数。您可以将结果用作`eval的合法第一个参数,并使用数据框作为环境:
dat <- data.frame(a=1:10,b=1:10)
eval( call( '+',quote(a),quote(b)), dat)
# [1] 2 4 6 8 10 12 14 16 18 20
问题的答案&#34;是公式的代价部分&#34;:可能,是的,如果我们要相信这一点:
(~a)[[1]]
#`~`
并从字符串&#34; a + b&#34;中构建功能结果。这将是一种方式:
as.call( parse(text="a+b") )
#(a + b)()
&#34; model.matrix重新绑定与公式关联的环境?&#34;
嗯,不完全是这样,至少我理解这个问题。 model.matrix
从model.frame中提取值,这是一个增强的数据帧,但它的属性列表中没有附加的环境。
看一些这些语言对象的属性很有意思:
> class(bquote(a+b))
[1] "call"
> identical( bquote(a+b), ~a+b)
[1] FALSE
> attributes( ~a+b)
$class
[1] "formula"
$.Environment
<environment: R_GlobalEnv>
> attributes( bquote(a+b))
NULL
Globalenv中的a = 1且b = 2,如上所述:
> eval( (~a+b)[[2]], envir=dat)
[1] 2 4 6 8 10 12 14 16 18 20
>
> eval( (~a+b)[[2]] )
[1] 3
附录:康拉德的评论,其中指出eval的论点可以是公式调用或表达式中的任何一个,因此您不需要as.call
,提示me furhter说明eval
和evalq
可以用来产生反映上述差异的结果,只有表达式a + b:
> evalq( a+b, envir=dat)
[1] 2 4 6 8 10 12 14 16 18 20
> eval( a+b, envir=dat) # evaluated in current scope despite envir=dat
[1] 3