进一步研究R评估的奥秘...这与我之前的问题(How to write an R function that evaluates an expression within a data-frame)密切相关。假设我要编写一个函数topfn,它接受一个数据帧和一个包含该数据帧的列名的表达式。我想将这两个参数传递给另一个函数fn,该函数实际上对数据框“环境”内的表达式求值。我希望fntopfn在传递数据框和表达式时都能正常工作

正如对上述问题的回答所建议的,我的第一个尝试是定义:

 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


就像我说的那样,这看起来很丑陋。是否有更好的方法(或更标准的习惯用语)使它们起作用?
我查阅了Lumley的名字奇特的标准非标准评估规则文件http://developer.r-project.org/nonstandard-eval.pdf,但在阅读后并没有特别的启发。我可以参考示例的任何指向函数源代码的指针也很有用。

最佳答案

通过将字符串而不是表达式传递给topfn可以最容易地避免这种情况。

topfn <- function(df, ex_txt)
{
  fn(df, ex_txt)
}

fn <- function(dfr, expr_txt)
{
   eval(parse(text = expr_txt), dfr)
}

df <- data.frame(a = 1:5, b = 1:5 )
fn(df, "a")
fn(df, "2 * a + b")
topfn(df, "a")
topfn(df, "2 * a + b")


编辑:

您可以让用户传入表达式,但是为了方便起见,请在下面使用字符串。

topfn更改为

topfn <- function(df, ex)
{
  ex_txt <- deparse(substitute(ex))
  fn(df, ex_txt)
}
topfn(df, a)
topfn(df, 2 * a + b)


另一个编辑:

这似乎可行:

topfn <- function(df, ex)
{
  eval(substitute(fn(df, ex)))
}

fn <- function(dfr, expr)
{
   eval(substitute(expr), dfr)
}
fn(df, a)
fn(df, 2 * a + b)
topfn(df, a)
topfn(df, 2 * a + b)

关于r - R:将表达式传递给内部函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4692231/

10-10 15:54