forcats::fct_reorder()
   get_help() docs


Description

The fct_reorder() function is part of the {forcats} package, which is part of the {tidyverse}.

We use the fct_reorder() function to quickly reorder of categories (levels) in a factor variable based on the order of values in another variable.

Changing the order of factor levels is commonly performed to change axis order of a factor variable when using plotting with the {ggplot2} library.

To use this function, you need to either first load the {forcats} library, or always use the function with forcats::fct_reorder() notation.

# Load the library
library(forcats)
# Or, load the full tidyverse:
library(tidyverse)

# Or, use :: notation
forcats::fct_reorder()

Conceptual Usage

fct_reorder(factor variable to change order of, other variable to order by)

fct_reorder(factor variable to change order of, 
            other variable to order by, 
            # Commonly used optional arguments:
            .fun = how to transform the other variable for re-ordering, 
            .desc = TRUE or FALSE) # Ordered in descending order, by default

Examples

The examples below use a modified version of the msleep dataset called msleep_fctvore. Learn more about this dataset with get_help("msleep").

In this modified dataset, the vore column has been coerced into a factor type (instead of character), and all NA values have been removed from that column. (Notice below, the vore column is annotated <fct> since it’s a factor).

# Show the modified msleep dataset, msleep_fctvore, with head()
head(msleep_fctvore)
## # A tibble: 6 × 11
##   name  genus vore  order conservation sleep_total sleep_rem sleep_cycle awake  brainwt  bodywt
##   <chr> <chr> <fct> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>    <dbl>   <dbl>
## 1 Owl … Aotus omni  Prim… <NA>                17         1.8      NA       7    0.0155    0.48 
## 2 Moun… Aplo… herbi Rode… nt                  14.4       2.4      NA       9.6 NA         1.35 
## 3 Grea… Blar… omni  Sori… lc                  14.9       2.3       0.133   9.1  0.00029   0.019
## 4 Cow   Bos   herbi Arti… domesticated         4         0.7       0.667  20    0.423   600    
## 5 Thre… Brad… herbi Pilo… <NA>                14.4       2.2       0.767   9.6 NA         3.85 
## 6 Nort… Call… carni Carn… vu                   8.7       1.4       0.383  15.3 NA        20.5

# Examples will reorder based on mean(awake), so this shows what to expect:
# Calculate and show the values of mean(awake) per vore. 
msleep_fctvore %>%
  group_by(vore) %>%
  summarize(mean_awake = mean(awake)) %>%
  arrange(mean_awake)
## # A tibble: 4 × 2
##   vore    mean_awake
##   <fct>        <dbl>
## 1 insecti       7.48
## 2 omni         13.0 
## 3 carni        14.3 
## 4 herbi        14.9


# reorder the order of `vore` levels according to _mean_ values of _awake_
msleep_fctvore %>%
  mutate(vore = fct_reorder(vore, 
                            awake, 
                            # This argument tells forcats to order vore by MEAN awake
                            .fun = mean)) -> msleep_fctvore_ex1

# Show new levels to confirm they are updated
levels(msleep_fctvore_ex1$vore)
## [1] "insecti" "omni"    "carni"   "herbi"


# reorder the order of `vore` levels according to _mean_ values of _awake_, but in descending order
msleep_fctvore %>%
  mutate(vore = fct_reorder(vore, 
                            awake, 
                            .fun = mean, # order vore by MEAN awake
                            .desc = TRUE)) -> msleep_fctvore_ex2

# Show new levels to confirm they are updated
levels(msleep_fctvore_ex2$vore)
## [1] "herbi"   "carni"   "omni"    "insecti"


# reorder the order of `vore` levels according to _mean_ values of _awake_, 
# Here, we first summarize the data so we need only to reorder by `mean_awake`, without needing a `.fun` argument
msleep_fctvore %>%
  group_by(vore) %>%
  summarize(mean_awake = mean(awake)) %>%
  mutate(vore = fct_reorder(vore, mean_awake)) -> msleep_fctvore_ex3

# Show new levels to confirm they are updated
levels(msleep_fctvore_ex3$vore)
## [1] "insecti" "omni"    "carni"   "herbi"


# Without re-writing the column, change the levels for _plotting purposes only_
# Provide fct_reorder(VARIABLE, OTHER VARIABLE, ...) to ggplot2::aes() to order in your plot
# This affects the x-axis labeling, so it is best practice to clean up with `labs()`

# For this plot, we'll reorder `vore` based on MINIMUM AWAKE values
# Recall: The R function to calculate minimums is `min()`
ggplot(msleep_fctvore) +
  aes(x = fct_reorder(vore, awake, .fun = min), 
      y = awake) + 
  geom_boxplot() + 
  labs(x = "vore")


# Without re-writing the column, change the levels for _plotting purposes only_
# Provide fct_reorder(VARIABLE, OTHER VARIABLE, ...) to ggplot2::aes() to order in your plot
# This affects the x-axis labeling, so it is best practice to clean up with `labs()`

# For this plot, we'll reorder `vore` based on its COUNT, using `dplyr::count()`
msleep_fctvore %>%
  count(vore) %>%
  ggplot() + 
  aes(x = fct_reorder(vore, n), 
      y = n) + 
  geom_col() + 
  labs(x = "vore")