进一步深入研究R评估的奥秘......这与我之前的问题(How to write an R function that evaluates an expression within a data-frame)密切相关。假设我想编写一个函数topfn
,它需要一个数据框和一个涉及该数据框的列名的表达式。我想将这两个参数都传递给另一个函数fn
,它实际上评估数据框“环境”中的表达式。 我希望当传递一个数据帧和表达R:将表达式传递给内部函数
我第一次尝试都fn
和topfn
正常工作,如在回答上述问题提出,是定义:
fn <- function(dfr, expr) {
mf <- match.call()
eval(mf$expr, envir = dfr)
}
并定义topfn
这样的:
topfn <- function(df, ex) {
mf <- match.call()
fn(df, mf$ex)
}
现在,如果我有一个数据帧
df <- data.frame(a = 1:5, b = 1:5)
内部功能fn
正常工作:
> fn(df,a)
[1] 1 2 3 4 5
但topfn
不起作用:
> topfn(df,a)
mf$ex
为了解决这个问题我先检查类topfn(df,a)
,
> class(topfn(df,a))
[1] "call"
这给了我一个丑陋的黑客重新定义的想法如下:
fn <- function(dfr, expr) {
mf <- match.call()
res <- eval(mf$expr, envir = dfr)
if(class(res) == 'call')
eval(expr, envir = dfr) else
res
}
现在无论职能的工作:
> fn(df,a)
[1] 1 2 3 4 5
> topfn(df,a)
[1] 1 2 3 4 5
正如我所说的,这看起来像一个丑陋的黑客。有没有更好的方法(或更标准的习惯用语)来使这些工作? 我已经咨询了Lumley的好奇命名的标准非标准评估规则文件http://developer.r-project.org/nonstandard-eval.pdf,但在阅读后并没有特别开悟。同样有帮助的是任何指向我可以查看示例的函数的源代码的指针。
有R上的评价由哈德利韦翰的主题在这里有很大的wiki:HTTPS: //github.com/hadley/devtools/wiki/Evaluation – 2011-01-14 23:57:06
正如我所建议的那样,您要仔细区分交互使用的函数和函数从其他功能被调用。调用任何使用替代和其他技巧的函数是非常困难的。换句话说,`fn`和`topfn`没有干净的方式来处理相同类型的输入 - 这是一件好事。 – hadley 2011-01-15 00:54:55
@hadley我明白了你的观点:为交互式应用设计的功能可以使用替代/其他技巧,以便在控制台上输入它们(即不用引号等)。而仅被设计为被其他函数调用的函数不应该使用这些技巧,因为它们可能会不可预测地中断。特别是@Richie在他的回答结束时提供的解决方案,即使它在我上面的特定情况下工作 - 当在其他情况下使用时,它可能会中断(尤其是`fn`) - 我认为这就是'重新说,对吧? – 2011-01-15 01:05:02