对R认知的困惑:假设我们有一个数据框:
df <- data.frame( a = 1:5, b = 1:5 )
我知道我们可以做像
这样的事情with(df, a)
获取结果向量。
但是我如何编写一个带有表达式的函数(例如a
或a > 3
)并在内部执行相同的操作。即我想编写一个函数fn
,它将数据框和表达式作为参数,并返回在数据框中“作为”环境评估表达式的结果。
没关系,这听起来很人为(我可以像上面那样使用with
),但这只是我正在编写的更复杂功能的简化版本。我尝试了几种变体(使用eval
,with
,envir
,substitute
,local
等),但它们都不起作用。例如,如果我像这样定义fn
:
fn <- function(dat, expr) {
eval(expr, envir = dat)
}
我收到此错误:
> fn( df, a )
Error in eval(expr, envir = dat) : object 'a' not found
显然,我遗漏了一些关于环境和评估的微妙之处。有没有办法定义这样的功能?
答案 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.table
与j
,i
和by
参数一起使用的方式。
如果您需要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
等等。在后台,这是使用substitute
和eval
答案 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