fct_reorder
fct_reorder(.f, .x, .fun = median, ..., .na_rm = NULL, .default = Inf, .desc = FALSE) Description
fct_reorder() changes the order of a factor’s levels based on a summary statistic computed from a second numeric vector. It groups the data by .f, applies .fun to .x within each group, then sorts the levels according to those summary values.
It is commonly used to reorder factors for plotting with ggplot2, where you want categorical axes ordered by the underlying data rather than alphabetical or arbitrary order.
Parameters
| Parameter | Type | Description |
|---|---|---|
.f | factor or character | The factor whose levels will be reordered |
.x | numeric | Determines the new level order |
.fun | function | Summary function applied to .x within each level; defaults to median |
... | any | Additional arguments passed to .fun |
.na_rm | NULL, TRUE, or FALSE | How to handle NAs in .x; see Gotchas |
.default | scalar | Where empty levels appear; Inf (last) or -Inf (first) |
.desc | logical | If TRUE, reverse the sort order |
Returns
A factor with the same values as .f but with levels reordered according to the summary of .x.
Examples
Basic usage
Reorder Species by median Sepal.Width in the iris dataset:
library(forcats)
iris$Species_ord <- fct_reorder(iris$Species, iris$Sepal.Width)
levels(iris$Species_ord)
# [1] "versicolor" "virginica" "setosa"
The default summary function is median. Versicolor has the lowest median sepal width (~2.8), virginica is in the middle (~3.0), and setosa has the highest (~3.4), so the ascending order is versicolor → virginica → setosa.
Descending order
Use .desc = TRUE to reverse the sort order:
iris$Species_ord_desc <- fct_reorder(iris$Species, iris$Sepal.Width, .desc = TRUE)
levels(iris$Species_ord_desc)
# [1] "setosa" "virginica" "versicolor"
Descending order with a custom function
You can pass a custom function and reverse the order with .desc = TRUE:
mtcars$carb_ordered <- fct_reorder(mtcars$carb, mtcars$hp, .fun = max, .desc = TRUE)
levels(mtcars$carb_ordered)
# [1] "4" "2" "3" "1"
Here, carburetors are ordered by maximum horsepower. Setting .desc = TRUE puts the highest values first.
Handling missing values
By default, NAs in .x produce a warning and are removed before computing the summary. You can silence the warning with .na_rm = TRUE:
x <- c(1, 2, NA, 4)
f <- factor(c("a", "a", "b", "b"))
fct_reorder(f, x)
# Warning: Removing NA values in fct_reorder
# [1] a b
# Levels: a < b
# Silently remove NAs
fct_reorder(f, x, .na_rm = TRUE)
# [1] a b
# Levels: a < b
Gotchas
- NAs in
.x: The default behavior (NULL) removes NAs with a warning. Set.na_rm = TRUEto suppress the warning, or.na_rm = FALSEto preserve NAs in the computation. - NAs in
.f: Factor levels that are NA are placed last regardless of sort direction. - Already-ordered factors: Calling
fct_reorder()on an ordered factor overrides the existing order. - Empty levels: Controlled by
.default. UseInf(default) for last position,-Inffor first position. - Ties: The ordering is deterministic, but the exact order among ties is unspecified.
See Also
factor()— create factors, the data type thatfct_reorder()operates ondplyr::arrange()— sort rows of a data frame by column values; complementary to reordering factor levelsfct_relevel— manually specify level order by explicitly listing which levels come firstfct_reorder2— reorder by two variables, useful for line plots where you want to match legend order