如果您运行:
mod <- lm(mpg ~ factor(cyl), data=mtcars)
Run Code Online (Sandbox Code Playgroud)
它运行,因为lm知道查看mtcars以找到mpg和cyl.
然而mean(mpg)失败,因为它找不到mpg,所以你这样做mean(mtcars$mpg).
你如何编写一个函数,以便它知道在'数据'中查找变量?
myfun <- function (a,b,data){
return(a+b)
}
Run Code Online (Sandbox Code Playgroud)
这将适用于:
myfun(mtcars$mpg, mtcars$hp)
Run Code Online (Sandbox Code Playgroud)
但会失败:
myfun(mpg,hp, data=mtcars )
Run Code Online (Sandbox Code Playgroud)
干杯
Jos*_*ien 20
这是我的编码方式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
Run Code Online (Sandbox Code Playgroud)
如果您熟悉with(),有趣的是看它的工作方式几乎完全相同:
> with.default
# function (data, expr, ...)
# eval(substitute(expr), data, enclos = parent.frame())
# <bytecode: 0x016c3914>
# <environment: namespace:base>
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,关键思想是首先从作为参数传入的符号创建表达式,然后使用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)
Run Code Online (Sandbox Code Playgroud)
或者,看看evalq.