传递数据框以在函数内变异

时间:2014-07-07 08:37:32

标签: r dplyr

我想传递一个数据框及其列,以便在函数中由dplyr进行处理。

这是一个例子

multifun <- function(dataf,vari){
 mutate(dataf,newvar=vari*2)
}

multifun(mtcars,gear)

这个功能的问题在于变量&#39; gear&#39;不是公认的对象。更具体地说,我得到了错误

  

mutate_impl(.data,named_dots(...),environment())对象出错   &#39;齿轮&#39;找不到

这是dplyr的mutate正在寻找相关变量的环境问题。

我理解

multifun(mtcars,mtcars$gear)

会给我一个我想要的答案,即

    mpg  cyl  disp  hp   drat  wt   qsec  vs am   gear carb newvar
1  21.0   6   160.0 110  3.90 2.620 16.46  0  1    4    4      8
2  21.0   6   160.0 110  3.90 2.875 17.02  0  1    4    4      8
3  22.8   4   108.0  93  3.85 2.320 18.61  1  1    4    1      8

但我想看看是否有办法避免在函数调用中引用数据框中使用的每个变量。

我也知道从函数调用中取出mutate没有问题。即,mutate(mtcars,newvar=gear*2)完成工作。但是,我试图理解dplyr的mutate在置于函数内时如何在不同的环境中查找有问题的变量。

4 个答案:

答案 0 :(得分:5)

这对我来说真的很难看,但似乎有效。基本上,我尝试使用get但它似乎不知道在哪里看,所以我指定了环境。

multifun <- function(dataf, vari){
  vari <- deparse(substitute(vari))
  mutate(dataf, newvar = get(vari, envir = as.environment(dataf)) * 2)
}

输出:

multifun(mtcars, gear)
#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb newvar
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4      8
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4      8
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1      8
# <<<SNIP>>>
# Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6     10
# Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8     10
# Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2      8

答案 1 :(得分:5)

看看@Anandas解决方案,这似乎是最简单的黑客

multifun <- function(dataf, vari){   
dataf <- mutate(dataf, newvar = dataf[, vari]*2);   
return(dataf) 
}

multifun(mtcars,"gear")

再次,考虑到@Anandas的建议,你也可以做

multifun <- function(dataf, vari){  
  vari <- deparse(substitute(vari))
  dataf <- mutate(dataf, newvar = dataf[, vari]*2)   
  return(dataf) 
}

multifun(mtcars, gear)

答案 2 :(得分:3)

或者

multifun1 <- function(dataf, vari){
eval(substitute(mutate(dataf, newvar=vari*2), list(vari=as.name(vari))))
}

multifun1(mtcars,"gear") 

要使用unquoted值,最好使用@Ananda Mahto的建议

multifun1 <- function(dataf, vari){
vari <- deparse(substitute(vari))
eval(substitute(mutate(dataf, newvar=vari*2), list(vari=as.name(vari))))
}

multifun1(mtcars,gear)

答案 3 :(得分:2)

使用dplyr 0.7.0,现在可以使用tidyeval完成此操作:

multifun <- function(dataf,vari){
  mutate(dataf,newvar = UQ(enquo(vari))*2)
}

multifun(mtcars,gear)

enquo引用引用函数参数的符号,并将其与调用函数的环境捆绑在一起。然后可以使用UQ!!取消引用quosure并立即在mutate内对其进行评估。