你如何编写一个R函数,以便'知道'在其他参数中查找'数据'中的变量?
如果你运行:
mod <- lm(mpg ~ factor(cyl), data=mtcars)
它运行,因为他知道在mtcars中查找mpg和cyl。
然而, mean(mpg)
因为找不到mpg而失败,所以你的mean(mtcars$mpg)
。
你如何编写一个函数,以便知道如何查找变量的“数据”?
myfun <- function (a,b,data){
return(a+b)
}
这将与:
myfun(mtcars$mpg, mtcars$hp)
但会失败:
myfun(mpg,hp, data=mtcars )
干杯
以下是我将如何编码myfun()
:
myfun <- function(a, b, data) {
eval(substitute(a + b), envir=data, enclos=parent.frame())
}
myfun(mpg, hp, mtcars)
# [1] 131.0 131.0 115.8 131.4 193.7 123.1 259.3 86.4 117.8 142.2 140.8 196.4
# [13] 197.3 195.2 215.4 225.4 244.7 98.4 82.4 98.9 118.5 165.5 165.2 258.3
# [25] 194.2 93.3 117.0 143.4 279.8 194.7 350.0 130.4
如果你熟悉with with()
,看到它的工作方式几乎完全相同:
> with.default
# function (data, expr, ...)
# eval(substitute(expr), data, enclos = parent.frame())
# <bytecode: 0x016c3914>
# <environment: namespace:base>
在这两种情况下,关键的想法是先从作为参数传入的符号创建一个表达式,然后使用data
作为评估的“环境”来评估该表达式。
第一部分(例如,将a + b
转换为mpg + hp
表达式)可以使用substitute()
。 第二部分是可能的,因为eval()
设计非常漂亮,可以将data.frame
作为其评估环境。
lm
“知道”查看它的data
参数,因为它实际上使用自己的调用作为基础构造对model.frame
的调用。 如果你看一下lm
的代码,你会在前十几行看到必要的机制。
你可以为了你自己的目的复制这个,但是如果你的需求更简单,你不必去相同的程度。 例如:
myfun <- function(..., data)
eval(match.call(expand.dots=FALSE)$...[[1]], data)
或者,只要看看evalq
。
这不完全像你所要求的,但如果你不知道with()
这可能是一个选择:
myfun <- function (a,b){
return(a+b)
}
with(mtcars, myfun(mpg, hp))
你可以删除myfun的data
参数。
下一篇: in Data Sets (PSA)?