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

时间:2011-01-13 16:50:47

标签: r lazy-evaluation evaluation

对R认知的困惑:假设我们有一个数据框:

df <- data.frame( a = 1:5, b = 1:5 )

我知道我们可以做像

这样的事情
with(df, a)

获取结果向量。

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

没关系,这听起来很人为(我可以像上面那样使用with),但这只是我正在编写的更复杂功能的简化版本。我尝试了几种变体(使用evalwithenvirsubstitutelocal等),但它们都不起作用。例如,如果我像这样定义fn

fn <- function(dat, expr) {
  eval(expr, envir = dat)
}

我收到此错误:

> fn( df, a )
Error in eval(expr, envir = dat) : object 'a' not found

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

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

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

答案 2 :(得分:2)

迟到的条目,但data.table方法和语法似乎就是你所追求的。 这正是[.data.tablejiby参数一起使用的方式。

如果您需要fn(x,expr)格式,则可以使用以下

library(data.table)

DT <- data.table(a = 1:5, b = 2:6)

`[`(x=DT, j=a)

## [1] 1 2 3 4 5

 `[`(x=DT, j=a * b)
## [1]  2  6 12 20 30

我认为以更原生的形式使用更容易

DT[,a]
## [1] 1 2 3 4 5

等等。在后台,这是使用substituteeval

答案 3 :(得分:-1)

?内也可能有意义。

 df <- data.frame( a = 1:5, b = 1:5 ) 
 within(df, cx <- a > 3)
   a b    cx
 1 1 1 FALSE
 2 2 2 FALSE
 3 3 3 FALSE
 4 4 4  TRUE
 5 5 5  TRUE