如何将data.frame中的列传递给内部具有dplyr函数的函数

时间:2014-09-02 02:42:41

标签: r function arguments dplyr

x <- y <- 1:5
df = data.frame(m=x,n=y)

myfun <- function(data, var) {
  library(dplyr)
   select(data, var)
}


myfun(df, m)

eval(expr,envir,enclos)中的错误:object&#39; m&#39;找不到

2 个答案:

答案 0 :(得分:2)

理查兹的答案可以绕过任意数量的参数。但要分别控制这种选择呼叫的每个参数,你必须知道: 在select(data, m)中,m 不是此时具有指定值的变量!它只是一个符号,它在数据框“数据”的上下文中有一些含义。一旦使用参数myfun(df, m)m将失败(在select-call中就是这种情况),因为m没有值(或来自全局环境的值,你肯定不想要!)在内部,dplyr将使用substitute函数将其转换为符号(而不是评估它)。将var转换为符号(或调用,例如m:n等选项)后,您可以使用do.call撰写和评估新的选择调用。

对于您的示例代码,这意味着:

x <- y <- 1:5
df = data.frame(m=x,n=y)

myfun <- function(data, var) {
  library(dplyr)
  var <- substitute(var)
  do.call('select', list(data, var))
}


myfun(df, m)

对更多论点的概括是直截了当的。

对于要转换为符号或调用的任意数量的参数,您可以使用

myfun <- function(...) {
  args <- substitute(list(...))
  # Now args[i] is a symbol/call representing the i-th argument
}

答案 1 :(得分:0)

select使用数据框架方法select.data.frameselect的第二个参数是...列表,以便可以将参数传递给其他方法。您的函数在其第二个参数中使用名称var,并且由于dplyr&#39; .()函数,基本R方差函数var正在传递给其他select内的函数。

长话短说,改变你的论点名称。我会选择

myfun <- function(z, ...) select(z, ...)
myfun(df, x)
myfun(df, y)

您还可以使用select方法

> select.myfun <- function(.data, ...) UseMethod("select")
> myfun(df, exclude = "x")
> methods(select)[6]
[1] "select.myfun"

作为一个无耻的插件,我会推荐你​​a question I asked about ... arguments。答案中有两个非常好的解释。

编辑根据要求,查看.()

> `.`
function (..., .env = parent.frame()) 
{
    structure(as.list(match.call()[-1]), env = .env, class = "quoted")
}
<environment: namespace:plyr>

> .(x)
List of 1
 $ x: symbol x
 - attr(*, "env")=<environment: R_GlobalEnv> 
 - attr(*, "class")= chr "quoted"