1
votes

I am writing a function to reorder columns in a tibble so that they are plotted by ggplot in a meaningful order, rather than alphabetically. This function is part of a package I am trying to write where I am allowing different column names for the tibble. I would like to do something like this:

reorder_samples <- function(tibble, col_name, fact_list)
{
    #where col_name is a string which is the title of the column to be factored 
    #and fact_list is a concatenated list of strings in the order I want for the factors
    factored_tibble <- tibble %>%
        mutate_at(col_name, as.factor) %>%
        mutate(!!col_name := fct_relevel(col_name, fact_list)
}

However, when I call this function, it gives me a warning message: "1: Unknown levels in 'f':" and then it gives the two items in my fact_list. These are the only two character strings in the column. Also, it does give me back a tibble, where the contents of the column have been replaced with the string of col_name.

It took me a long time to figure out how to get mutate to use the arguments supplied in my function and I haven't been able to figure out what the syntax should be for forcats so it realizes that I am referring to a column name. If I replace the column name directly into the code it works:

reorder_samples <- function(tibble, col_name, fact_list)
{
    factored_tibble <- tibble %>%
        mutate_at(col_name, as.factor) %>%
        mutate(!!col_name := fct_relevel(Temp, fact_list)
}

I have also tried to use the base r function factor with no luck as I could not get factor to take an argument either.

Hopefully this is clear and thanks for any advice in advance.

1

1 Answers

0
votes

Assuming that 'col_name' is passed as a string and fact_list as a character vector in the mutate_at, wrap the 'col_name' in vars, then in the mutate step, convert it to symbol and evaluate (!!) on the rhs of :=

library(dplyr)
library(forcats)
reorder_samples <- function(tibble, col_name, fact_list){

  tibble %>%
    mutate_at(vars(col_name), as.factor) %>%
    mutate(!!col_name := fct_relevel(!! rlang::sym(col_name), fact_list))

   }

Using a reproducible example

data(iris)
levels(iris$Species)
#[1] "setosa"     "versicolor" "virginica" 

newlvls <- c("virginica", "setosa", "versicolor")
out <- reorder_samples(iris, "Species", newlvls)
levels(out$Species)
#[1] "virginica"  "setosa"     "versicolor"