forcats fct_relevel() in R: Reorder Factor Levels
The fct_relevel() function in forcats reorders the levels of a factor by hand. You name the levels you want moved, and it puts them where you ask while leaving every other level in place.
fct_relevel(f, "Low") # move one level to the front fct_relevel(f, "Low", "Mid", "High") # set the full order explicitly fct_relevel(f, c("Low", "Mid")) # pass the levels as a vector fct_relevel(f, "High", after = 1) # insert after position 1 fct_relevel(f, "Low", after = Inf) # send a level to the end fct_relevel(f, rev) # reorder with a function fct_relevel(f, sort) # sort levels alphabetically
Need explanation? Read on for examples and pitfalls.
What fct_relevel() does
fct_relevel() changes the order of a factor's levels without touching the data. A factor stores its categories as an ordered set of levels, and by default R sorts those levels alphabetically. That alphabetical order is rarely the order you want in a plot, a model summary, or a table. fct_relevel() lets you override it.
The values in the factor stay exactly the same. Only the level order changes, which controls how the categories appear on chart axes, in regression output, and anywhere the factor is sorted. This matters most for two jobs: putting a logical sequence on an ordinal variable like Low, Medium, High, and setting the reference level for a regression model.
fct_relevel() only rewrites the lookup table order and remaps the codes to match. No observation is added, dropped, or relabelled.fct_relevel() syntax
fct_relevel() takes a factor, the levels to move, and an optional position. The full signature is short:
fct_relevel(.f, ..., after = 0L)
.fis a factor (a character vector is coerced to one)....is one or more level names to move, or a single function.afteris the position the moved levels are inserted after. The default0Lmeans the front.
The levels came back alphabetically: High, Low, Medium. That is the order fct_relevel() will fix in the examples below.
fct_relevel() examples
Each example moves levels on the same sizes factor. fct_relevel() always returns a new factor, so assign the result to keep it.
1. Move one level to the front
Naming a single level promotes it to first position. The rest keep their relative order.
This is the pattern for setting a regression reference level: the first level becomes the baseline that other coefficients are compared against.
2. Set the full order explicitly
List every level in the order you want. This is the clearest option for ordinal data.
3. Insert a level at a chosen position
Use after to drop a level into a specific slot instead of the front. Here after = 1 places High after the first remaining level.
after = Inf to send a level to the very end. fct_relevel(sizes, "Low", after = Inf) produces High, Medium, Low. This is handy for pushing an "Other" or "Unknown" bucket to the bottom of a chart legend.4. Reorder with a function
If you pass a function instead of level names, fct_relevel() applies it to the current level vector and uses the result as the new order.
fct_relevel() vs other forcats ordering functions
fct_relevel() is the manual option; the others derive order from the data. Reach for fct_relevel() when you already know the order you want. When the order should follow a statistic or a count, a sibling function is a better fit.
| Function | Orders levels by | Use when |
|---|---|---|
fct_relevel() |
a manual specification | you know the exact order you want |
fct_reorder() |
another numeric variable | order should track a summary value |
fct_infreq() |
frequency (most common first) | the popular category should lead |
fct_inorder() |
order of first appearance | data already arrives in a meaningful sequence |
fct_rev() |
reversing the current order | you only need to flip the existing order |
The decision rule is simple: if a human picks the order, use fct_relevel(); if the data picks the order, use one of the others.
Common pitfalls
Pitfall 1: misspelling a level name. fct_relevel() does not error on an unknown level. It emits a warning and leaves that level untouched, so a typo silently produces the wrong order.
Pitfall 2: expecting in-place modification. fct_relevel() returns a new factor and never changes the original. If you forget to assign the result, the reorder is lost.
after counts positions among the levels that stay put. It does not count the original level positions. With three levels, after = 1 inserts the moved level into the second slot, regardless of where that level started. When in doubt, list every level explicitly instead of using after.Pitfall 3: confusing reordering with renaming. fct_relevel() never changes a label. To rename a level, use fct_recode(); to merge several levels into one, use fct_collapse().
Try it yourself
Try it: The ex_days factor has its levels in alphabetical order. Reorder them to Mon, Wed, Fri and save the result to ex_ordered.
Click to reveal solution
Explanation: Listing every level by name gives fct_relevel() the complete target order. The factor values are unchanged; only the level lookup table is reordered.
Related forcats functions
After fct_relevel(), these forcats functions cover the rest of factor-order work:
fct_reorder(): order levels by a summary of another variable, ideal before plotting.fct_infreq(): order levels from most to least common.fct_inorder(): order levels by when each value first appears.fct_rev(): reverse the current level order in one call.fct_recode(): rename levels without changing their order.
For the bigger picture on how factors store and display categories, see the forcats reference at forcats.tidyverse.org.
FAQ
What does fct_relevel do in R?
fct_relevel() reorders the levels of a factor by hand. You pass the factor and the level names in the order you want, and it returns a new factor with that level order. The underlying observations are not changed, so it is safe to use purely for display and modelling purposes, such as fixing chart axis order.
How do I move a factor level to the end with fct_relevel?
Use the after argument set to Inf: fct_relevel(f, "Other", after = Inf) moves the Other level to the last position. Any finite after value inserts the level after that many remaining positions, so after = 0 is the front and after = Inf is the back.
What is the difference between fct_relevel and fct_reorder?
fct_relevel() sets the level order manually from names you supply. fct_reorder() sets the order automatically from another variable, for example sorting groups by their median value. Use fct_relevel() for ordinal data with a known sequence, and fct_reorder() when you want bars or boxes sorted by a statistic.
Does fct_relevel change the data values?
No. fct_relevel() only changes the order of the level labels and remaps the integer codes to match. Every observation keeps the same category. This is why it is safe to apply right before plotting or modelling without affecting counts, means, or any other computed result.
Can fct_relevel reorder levels without naming each one?
Yes. Pass a function instead of level names and fct_relevel() applies it to the current level vector. fct_relevel(f, sort) sorts levels alphabetically and fct_relevel(f, rev) reverses them. This is useful when the rule is mechanical rather than a hand-picked sequence.