深入探究 R 评估的奥秘... 这与我的上一个问题密切相关(如何编写一个在数据框内评估表达式的 R 函数)。假设我想编写一个函数 topfn
,它接受一个数据框和涉及该数据框列名的表达式作为参数。我想将这两个参数都传递给另一个函数 fn
,该函数实际上在数据框的“环境”中评估表达式。而且当传递数据框和表达式时,我希望 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
来实现:
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
就像我所说的,这看起来像是一个丑陋的hack。是否有更好的方法(或更标准的习惯用法)让这些工作起来?我已经查阅了Lumley的奇怪命名的《标准非标准评估规则文档》http://developer.r-project.org/nonstandard-eval.pdf 但在阅读后并没有特别大的收获。如果能提供任何指向示例函数源代码的指针也会很有帮助。
fn
和topfn
同时处理相同类型的输入 - 这是一件好事。 - hadleyfn
),我想这就是你的意思,对吗? - Prasad Chalasani