2015-04-22 42 views
5

我想编写一个函数,用于评估数据框中的表达式,但使用可能包含或不包含用户定义的表达式的表达式,定义的对象。 我觉得这个魔法词是“非标准评估”,但我还不能完全弄明白。R:使用作为对象传递的参数来评估数据框中的表达式

一个简单的例子(对于我的目的来说是现实的):说,我想评估一个lm()调用在数据框中找到的变量。

mydf <- data.frame(x=1:10, y=1:10) 

,它因此可以写成一个函数如下:

f <- function(df, expr){ 
    expr <- substitute(expr) 
    pf <- parent.frame() 
    eval(expr, df, pf) 
} 

这样的,我得到了我想要使用下面的命令是什么。

f(mydf, lm(y~x)) 

# Call: 
# lm(formula = y ~ x) 
# 
# Coefficients: 
# (Intercept)   x 
# 1.12e-15  1.00e+00 

不错。但是,有些情况下,在调用lm()之前将模型方程保存在对象中更方便。不幸的是,上述功能不再适用。

fml <- y~x 

f(mydf, lm(fml)) 
# Error in eval(expr, envir, enclos): object 'y' not found 

有人可以解释为什么第二个电话不起作用吗?这个函数怎么可能被改变,这样两个调用都会导致期望的结果? (希望=适合型号)

干杯!

回答

4

?lm,重新data说法:

如果数据未找到,变量从环境中获取(公式)

在你的第一种情况下,该公式是在eval(expr, df, pf)创建呼叫,所以公式的环境是基于df的环境。在第二种情况下,公式是在全球环境中创建的,这就是为什么它不起作用。

因为公式带有自己的环境,所以在NSE中处理它们可能会非常棘手。

你可以尝试:

with(mydf, 
    { 
    print(lm(y~x)) 
    fml <- y~x 
    print(lm(fml)) 
    } 
) 

但这可能不是您理想的选择。检查捕获的参数中的任何名称是否解析为公式并重新分配其环境,都会遇到一些麻烦。 更糟糕的是,重新分配环境并不一定是显而易见的。在许多情况下,你确实想看看公式环境。

有R上聊天在这一问题上松散的相关讨论:

+0

我想我明白你的意思,虽然我也词组它有点不同。让我看看我是否明白这一点:问题在于'eval()'必须在'lm()'可以作为一个整体进行评估之前查找对象'fml'。由于'fml'在数据框中不可用,'eval'可以通过'pf'找到它。该公式是在那里找到的,因为它是在那里创建的,但不会看到“y”或“x”。 – SimonG

+1

@SimonG问题不在于'eval'。问题在于'lm'在'environment'(公式)'中查找变量,而不考虑lm'调用的评估帧。 – BrodieG