38

我注意到相当多的包允许您传递在调用函数的上下文中甚至可能无效的符号名称。我想知道这是如何工作的以及如何在我自己的代码中使用它?

这是 ggplot2 的示例:

a <- data.frame(x=1:10,y=1:10)
library(ggplot2)
qplot(data=a,x=x,y=y)

x并且y不存在于我的命名空间中,但 ggplot 知道它们是数据框的一部分,并将它们的评估推迟到它们有效的上下文中。我试过做同样的事情:

b <- function(data,name) { within(data,print(name)) }
b(a,x)

然而,这惨遭失败:

Error in print(name) : object 'x' not found

我究竟做错了什么?这是如何运作的?

注意:这不是将变量名称传递给 r 中的函数的副本

4

4 回答 4

39

我最近发现了我认为传递变量名的更好方法。

a <- data.frame(x = 1:10, y = 1:10)

b <- function(df, name){
    eval(substitute(name), df)
}

b(a, x)
  [1]  1  2  3  4  5  6  7  8  9 10

更新该方法使用非标准评估。我开始解释,但很快意识到 Hadley Wickham 做得比我好得多。阅读此http://adv-r.had.co.nz/Computing-on-the-language.html

于 2015-12-04T02:04:08.980 回答
17

您可以使用match.call例如:

b <-  function(data,name) {

  ## match.call return a call containing the specified arguments 
  ## and the function name also 
  ## I convert it to a list , from which I remove the first element(-1)
  ## which is the function name

  pars <- as.list(match.call()[-1])
  data[,as.character(pars$name)]

}

 b(mtcars,cyl)
 [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4

解释:

match.call 返回一个调用,其中所有指定的参数都由它们的全名指定。

所以这里的输出match.call是2个符号:

b <-  function(data,name) {
  str(as.list(match.call()[-1]))  ## I am using str to get the type and name
}

b(mtcars,cyl)
List of 2
 $ data: symbol mtcars
 $ name: symbol cyl

所以然后我使用第一个符号 mtcars ansd 将第二个符号转换为字符串:

mtcars[,"cyl"]

或相当于:

eval(pars$data)[,as.character(pars$name)]
于 2013-10-02T09:46:52.037 回答
7

非常旧的线程,但您也可以使用该get命令。它似乎对我更好。

a <- data.frame(x = 1:10, y = 11:20)

b <- function(df, name){

   get(name, df)

 }

b(a, "x")
 [1]  1  2  3  4  5  6  7  8  9 10 
于 2019-10-24T19:48:39.600 回答
4

如果在调用函数时将变量名放在引号之间,它会起作用:

> b <- function(data,name) { within(data,print(name)) }
> b(a, "x")
[1] "x"
    x  y
1   1  1
2   2  2
3   3  3
4   4  4
5   5  5
6   6  6
7   7  7
8   8  8
9   9  9
10 10 10
于 2013-12-10T20:05:21.313 回答