你如何编写一个R函数,以便它"知道"在其他参数中查找变量的'data'?

nzc*_*ops 20 r

如果您运行:

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作为其评估环境.


Hon*_*Ooi 5

lm"知道"查看它的data参数,因为它实际上构造了一个model.frame使用自己的调用作为基础的调用.如果您查看代码lm,您将在前十几行中看到必要的机器.

你可以为自己的目的复制这个,但如果你的需求更简单,你就不必去相同的程度.例如:

myfun <- function(..., data)
eval(match.call(expand.dots=FALSE)$...[[1]], data)
Run Code Online (Sandbox Code Playgroud)

或者,看看evalq.