`with`用法里面的功能(包装)

时间:2011-12-05 15:26:20

标签: r function wrapper

我想编写一个自定义函数的包装器,它将一些向量作为输入(如:mtcars$hpmtcars$am等)以输入作为数据框名称(如{{1} }参数,例如:data)和变量名称(如:mtcarshp),与大多数标准函数一样。

但是我遇到了一些问题,我提出的'demo'功能(am的包装不起作用。

代码:

mean

对矢量运行当然有效:

f <- function(x, data=NULL) {
    if (!missing(data)) {
        with(data, mean(x))
    } else {
        mean(x)
    }
}

> f(mtcars$hp) [1] 146.69 不幸失败了:

with

在全球环境中/没有我的自定义功能正常工作:

> f(hp, mtcars)
Error in with(d, mean(x)) : object 'hp' not found

我尝试使用> with(mtcars, mean(hp)) [1] 146.69 substitute和其他人进行一些实验,但没有取得任何成功。任何暗示都会受到欢迎!

3 个答案:

答案 0 :(得分:10)

这是拼图的关键部分:

f <- function(x,data=NULL) {
  eval(match.call()$x,data) # this is mtcars$hp, so just take the mean of it or whatever
}

> f(hp,mtcars)
 [1] 110 110  93 110 175 105 245  62  95 123 123 180 180 180 205 215 230  66  52  65  97 150 150 245 175  66
[27]  91 113 264 175 335 109

# it even works without a data.frame specified:
> f(seq(10))
 [1]  1  2  3  4  5  6  7  8  9 10

请参阅@Andrie与@Hadley文档的链接,了解其工作原理。请参阅@ Hadley的注释,注意一个重要的警告:f()不能从另一个函数内部运行。

基本上R使用惰性评估(例如,在实际使用之前它不会对事物进行评估)。所以你可以通过传递它hp,因为它仍然是一个未经评估的符号,直到它出现在某个地方。由于match.call将它作为一个符号并等待评估它,一切都很好。

然后eval在指定的环境中对其进行评估。根据{{​​1}},第二个参数代表:

  

要评估expr的环境。也可能是NULL,a   列表,数据框,pairlist或sys.call指定的整数。

因此,无论是NULL(如果你没有传递data.frame)还是data.frame,你的状态都很好。

延迟评估的证明是这不会返回错误(因为x从未在函数中使用过):

?eval

答案 1 :(得分:3)

f <- function(x, data=NULL) {
    if (!missing(data)) { colname=deparse(substitute(x))
         mean(data[[colname]])
    } else {
        mean(x)
    }
}

 f(hp, mtcars)
[1] 146.6875

(不可否认,它不像@ gsk那样紧凑,我想我会试着记住他的方法而不是我的。感谢Josh O'Brien指出了一个现在已修复的错误。)

答案 2 :(得分:-1)

试试这个:

f <- function(x, data = NULL) {
     if (is.null(data)) {
         mean(x)
     } else { 
         attach(data)
         mean(x)
         detach(data)
     }
 }

同样在您的示例中,您输入数据集而不是列。 你的例子应该是f(hp,mtcars)