ifelse - dplyr sin codificar los nombres de las variables
funcion mutate en r (3)
El gran Hadley Wickham mismo (¡santificado sea su nombre!) Sugirió this en los mutatr
Google 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
¿Es posible usar la función de mutar de dplyr sin codificar los nombres de las variables? Por ejemplo, el siguiente código funciona, porque codifiqué el nombre 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
Sin embargo, cuando hago que el nombre de la variable sea una variable, ya no funciona:
> 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
Las funciones eval () y as.symbol () tampoco parecen ayudar.
En la versión de desarrollo de dplyr
(a la espera de la nueva versión 0.6.0
), con la introducción de quosures
y funciones quosures
( !!
, UQ
) para evaluar las citas en group_by/summarise/mutate
, esto se vuelve más fácil.
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
También tiene otras características para pasar nombres de columna.
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
También podemos crear una función y pasar el argumento.
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
En la función anterior, enquo
hace la funcionalidad similar como substitute
de la base R
al tomar los argumentos de entrada del usuario y convertirlos en quosure
. Como necesitamos el nombre de la columna en la cadena, podemos usar quo_name
para hacer la conversión a la cadena y la evaluación dentro de la llamada de mutate
se realiza sin citar ( !!
o UQ
)
datos
d <- expand.grid(1:3, 20:22)
Puede usar get
y precisar el entorno en el que se encuentra el objeto "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
Le sugiero que lea más sobre la "evaluación no estándar" en el wiki de "Programación avanzada R" de Hadley Wickham: http://adv-r.had.co.nz/Computing-on-the-language.html
EDITAR
Esta respuesta fue votada recientemente, así que me di cuenta de que la solución que di hace un año y medio no era realmente buena y aprovecho esta oportunidad para actualizar mi respuesta.
Desde dplyr 0.3 puede usar la versión de evaluación estándar de las funciones de dplyr, usando sus versiones "fun_".
También tiene que usar interp
from the lazyeval package si está haciendo algunos cálculos sobre las variables:
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