Reputation: 1030
I am trying to perform a task in dplyr in which non-standard and standard evaluation should be combined, but I could not find a convenient solution. I want to reorder a level based on another column in the data.frame (needed for a visualisation):
df <- data.frame(A = c(1,2,5,4), B = c("A", "B", "C","D"))
levels(df$B)
df2 <- df %>% mutate(B = factor(B, levels = unique(B)[order(A, decreasing = FALSE)]))
levels(df$B)
So far, so good. But now I want to do exactly the same task but B is the input of a function:
ReorderFactor <- function(column_name){
df2 <- df %>% mutate(column_name = factor(column_name, levels = unique(column_name)[order(A, decreasing = FALSE)]))
return(df2)
}
ReorderFactor(column_name = "B")
So I want to combine both standard and non-standard evaluation. I am searching for a dplyr approach.
Upvotes: 0
Views: 313
Reputation: 17632
You can use mutate_at
and then refer to the variable being mutated as .
ReorderFactor <- function(column_name){
df2 <- df %>%
mutate_at(column_name, funs(factor(., levels = unique(.)[order(A, decreasing = FALSE)])) )
return(df2)
}
Upvotes: 2
Reputation: 886938
We can use the quosure
from the devel version of dplyr
(soon to be released 0.6.0
)
ReorderFactor <- function(dat, column_name){
column_name <- enquo(column_name)
nm1 <- quo_name(column_name)
dat %>%
mutate(UQ(nm1) := factor(UQ(column_name),
levels = unique(UQ(column_name))[order(A, decreasing = FALSE)]))
}
dfN <- ReorderFactor(df, B)
identical(df2, dfN)
#[1] TRUE
Here, the enquo
takes the input argument and converts to a quosure
which is evaluated within the mutate/summarise
etc by unquoting(UQ
). Note that we are able to assign (:=
) the values on the lhs
by unquoting the string ('nm1')
NOTE: Here, we included 'dat' as another argument in case the function needs to be applied on a different dataset
Upvotes: 2