繁体   English   中英

dplyr没有对变量名进行硬编码

[英]dplyr without hard-coding the variable names

是否可以使用dplyr的mutate函数而无需对变量名进行硬编码? 例如,以下代码有效,因为我硬编码名称Var1:

            > d=expand.grid(1:3, 20:22)
            > d
            Var1 Var2
            1    1   20
            2    2   20
            3    3   20
            4    1   21
            5    2   21
            6    3   21
            7    1   22
            8    2   22
            9    3   22
            > d=mutate(d, x=percent_rank(Var1))
            > d
            Var1 Var2     x
            1    1   20 0.000
            2    2   20 0.375
            3    3   20 0.750
            4    1   21 0.000
            5    2   21 0.375
            6    3   21 0.750
            7    1   22 0.000
            8    2   22 0.375
            9    3   22 0.750

但是,当我将变量的名称变为变量时,它不再起作用:

            > my.variable='Var1'
            > d=mutate(d, x=percent_rank(my.variable))
            > d
                Var1 Var2   x
            1    1   20 NaN
            2    2   20 NaN
            3    3   20 NaN
            4    1   21 NaN
            5    2   21 NaN
            6    3   21 NaN
            7    1   22 NaN
            8    2   22 NaN
            9    3   22 NaN

eval()和as.symbol()函数似乎也没有帮助。

伟大的哈德利韦翰自己(!神圣的是他的名字)建议mutatr谷歌群组:

d <- expand.grid(1:3, 20:22)
my.variable <- 'Var1'
percent_rank <- function(x) rank(x)/max(rank(x))
call <- substitute(mutate(d, percent_rank(var)), 
                   list(var = as.name(my.variable)))
eval(call)
#   Var1 Var2 percent_rank(Var1)
# 1    1   20              0.250
# 2    2   20              0.625
# 3    3   20              1.000
# 4    1   21              0.250
# 5    2   21              0.625
# 6    3   21              1.000
# 7    1   22              0.250
# 8    2   22              0.625
# 9    3   22              1.000

您可以使用get和精确对象“Var1”所在的环境。

> my.variable = 'Var1'
> mutate(d, x = percent_rank(get(my.variable, envir = as.environment(d))))
  Var1 Var2     x
1    1   20 0.000
2    2   20 0.375
3    3   20 0.750
4    1   21 0.000
5    2   21 0.375
6    3   21 0.750
7    1   22 0.000
8    2   22 0.375
9    3   22 0.750

我建议你在Hadley Wickham的“高级R编程”维基上阅读更多关于“非标准评估”的内容: http//adv-r.had.co.nz/Computing-on-the-language.html

编辑

这个答案最近被投了票,所以我意识到我一年半前给出的解决方案并不是很好,我借此机会升级我的答案。

从dplyr 0.3开始,你可以使用dplyr函数的标准评估版本,使用它们的“fun_”版本。

你也需要使用interp如果你正在做的一些变量计算从lazyeval包:

my.variable = "Var1"
expr <- lazyeval::interp(~percent_rank(x), x = as.name(my.variable))
mutate_(d, .dots = setNames(list(expr), "x"))
Var1 Var2     x
1    1   20 0.000
2    2   20 0.375
3    3   20 0.750
4    1   21 0.000
5    2   21 0.375
6    3   21 0.750
7    1   22 0.000
8    2   22 0.375
9    3   22 0.750

dplyr版本的dplyr (等待新版本0.6.0 )中,引入quosures和unquote函数( !!UQ )来评估group_by/summarise/mutate的引号,这变得更容易

 my.variable <- quo(Var1)
 percent_rank <- function(x) rank(x)/max(rank(x))
 d %>% 
   mutate(x = percent_rank(!!my.variable))
#  Var1 Var2     x
#1    1   20 0.250
#2    2   20 0.625
#3    3   20 1.000
#4    1   21 0.250
#5    2   21 0.625
#6    3   21 1.000
#7    1   22 0.250
#8    2   22 0.625
#9    3   22 1.000

它还具有传递列名称的其他功能

mynewvar <- 'x'
d %>% 
   mutate(!!mynewvar := percent_rank(!!my.variable))
#  Var1 Var2     x
#1    1   20 0.250
#2    2   20 0.625
#3    3   20 1.000
#4    1   21 0.250
#5    2   21 0.625
#6    3   21 1.000
#7    1   22 0.250
#8    2   22 0.625
#9    3   22 1.000

我们也可以创建一个函数并传递参数

f1 <- function(dat, myvar, colN){
  myvar <- enquo(myvar)
  colN <- quo_name(enquo(colN))

  dat %>%
      mutate(!!colN := percent_rank(!!myvar))
 }

f1(d, Var1, x)
#  Var1 Var2     x
#1    1   20 0.250
#2    2   20 0.625
#3    3   20 1.000
#4    1   21 0.250
#5    2   21 0.625
#6    3   21 1.000
#7    1   22 0.250
#8    2   22 0.625
#9    3   22 1.000

在上面的函数, enquo确实的类似的功能性substitutebase R在拍摄用户输入参数和将其转换为quosure 由于我们需要字符串中的列名,我们可以使用quo_name进行字符串转换,而mutate调用中的评估是通过取消引用( !!UQ )完成的

数据

d <- expand.grid(1:3, 20:22)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM