如何编写一个R函数来计算数据框中的表达式

Pra*_*ani 9 evaluation r lazy-evaluation

R Cognoscenti的难题:假设我们有一个数据框架:

df <- data.frame( a = 1:5, b = 1:5 )
Run Code Online (Sandbox Code Playgroud)

我知道我们可以做的事情

with(df, a)
Run Code Online (Sandbox Code Playgroud)

获得结果的向量.

但是我如何编写一个带有表达式(如aor a > 3)的函数并在内部执行相同的操作.即我想编写一个函数fn,它将数据框和表达式作为参数,并返回在数据框中"作为"环境评估表达式的结果.

没关系,这听起来很人为(我可以with像上面一样使用),但这只是我正在编写的更复杂功能的简化版本.我试过几个变种(使用eval,with,envir,substitute,local,等),但他们没有工作.例如,如果我这样定义fn:

fn <- function(dat, expr) {
  eval(expr, envir = dat)
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

> fn( df, a )
Error in eval(expr, envir = dat) : object 'a' not found
Run Code Online (Sandbox Code Playgroud)

显然,我遗漏了一些关于环境和评估的微妙之处.有没有办法定义这样的功能?

Ric*_*ton 11

晶格包以不同的方式做这种事情.参见,例如,lattice:::xyplot.formula.

fn <- function(dat, expr) {
  eval(substitute(expr), dat)
}
fn(df, a)             # 1 2 3 4 5
fn(df, 2 * a + b)     # 3 6 9 12 15
Run Code Online (Sandbox Code Playgroud)


Jor*_*eys 10

那是因为你没有传递表达.

尝试:

fn <- function(dat, expr) {
  mf <- match.call() # makes expr an expression that can be evaluated
 eval(mf$expr, envir = dat)
}

> df <- data.frame( a = 1:5, b = 1:5 )
> fn( df, a )
[1] 1 2 3 4 5
> fn( df, a+b )
[1]  2  4  6  8 10
Run Code Online (Sandbox Code Playgroud)

使用它(例如lm)快速浏览一下函数的源代码可以揭示更多有趣的事情.