R:将表达式传递给内部函数 [英] R: passing expression to an inner function

查看:85
本文介绍了R:将表达式传递给内部函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

进一步研究R评估的奥秘...这与我之前的问题(而且我希望fntopfn在传递数据框和表达式时都能正常工作

Further delving into the mysteries of R evaluation...This is closely related to my previous question ( How to write an R function that evaluates an expression within a data-frame ). Let's say I want to write a function topfn that takes a data-frame and an expression involving column-names of that data-frame. I want to pass both these arguments on to another function fn that actually evaluates the expression within the "environment" of the data-frame. And I want both fn and topfn to work correctly when passed a data-frame and an expression

根据上述问题的答案,我的第一个尝试是定义:

My first attempt, as suggested in the answer to the above question, is to define:

 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)的类,

To fix this I first check the class of topfn(df,a),

> class(topfn(df,a))
[1] "call"

这为我提供了一个丑陋的方法,可以重新定义fn,如下所示:

This gives me an idea for an ugly hack to re-define fn as follows:

fn <- function(dfr, expr) {
  mf <- match.call()
  res <- eval(mf$expr, envir = dfr)  
  if(class(res) == 'call')
    eval(expr, envir = dfr) else
  res
}

现在这两个功能都可以工作:

And now both functions work:

> 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 ,但阅读后并没有特别的启发.对于我可以查看示例的函数源代码的任何指针,也将有所帮助.

As I said, this looks like an ugly hack. Is there a better way (or more standard idiom) to get these working? I've consulted Lumley's curiously-named Standard NonStandard Evaluation Rules document http://developer.r-project.org/nonstandard-eval.pdf but wasn't particularly enlightened after reading it. Also helpful would be any pointers to source-code of functions I can look at for examples.

推荐答案

通过将字符串传递到topfn而不是表达式中,最容易避免这种情况.

This is most easily avoided by passing strings into topfn instead of expressions.

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")

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

You could let the user pass expressions in, but use strings underneath for your convenience.

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:将表达式传递给内部函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆