[英]dplyr: how to avoid hard coding variable names when I need them all?
[英]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
确实的类似的功能性substitute
从base R
在拍摄用户输入参数和将其转换为quosure
。 由于我们需要字符串中的列名,我们可以使用quo_name
进行字符串转换,而mutate
调用中的评估是通过取消引用( !!
或UQ
)完成的
d <- expand.grid(1:3, 20:22)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.