15.10 Changing the Names of Factor Levels
15.10.2 Solution
Use fct_recode()
from the forcats package
factor(c( "small", "large", "large", "small", "medium"))
sizes <-
sizes#> [1] small large large small medium
#> Levels: large medium small
# Pass it a named vector with the mappings
fct_recode(sizes, S = "small", M = "medium", L = "large")
#> [1] S L L S M
#> Levels: L M S
15.10.3 Discussion
If you want to use two vectors, one with the original levels and one with the new ones, use do.call()
with fct_recode()
.
c("small", "medium", "large")
old <- c("S", "M", "L")
new <-
# Create a named vector that has the mappings between old and new
setNames(old, new)
mappings <-
mappings#> S M L
#> "small" "medium" "large"
# Create a list of the arguments to pass to fct_recode
c(list(sizes), mappings)
args <-
# Look at the structure of the list
str(args)
#> List of 4
#> $ : Factor w/ 3 levels "large","medium",..: 3 1 1 3 2
#> $ S: chr "small"
#> $ M: chr "medium"
#> $ L: chr "large"
# Use do.call to call fct_recode with the arguments
do.call(fct_recode, args)
#> [1] S L L S M
#> Levels: L M S
Or, more concisely, we can do all of that in one go:
do.call(
fct_recode,c(list(sizes), setNames(c("small", "medium", "large"), c("S", "M", "L")))
)#> [1] S L L S M
#> Levels: L M S
For a more traditional (and clunky) base R method for renaming factor levels, use the levels()<-
function:
factor(c( "small", "large", "large", "small", "medium"))
sizes <-
# Index into the levels and rename each one
levels(sizes)[levels(sizes) == "large"] <- "L"
levels(sizes)[levels(sizes) == "medium"] <- "M"
levels(sizes)[levels(sizes) == "small"] <- "S"
sizes#> [1] S L L S M
#> Levels: L M S
If you are renaming all your factor levels, there is a simpler method. You can pass a list to levels()<-
:
factor(c("small", "large", "large", "small", "medium"))
sizes <-levels(sizes) <- list(S = "small", M = "medium", L = "large")
sizes#> [1] S L L S M
#> Levels: S M L
With this method, all factor levels must be specified in the list; if any are missing, they will be replaced with NA
.
It’s also possible to rename factor levels by position, but this is somewhat inelegant:
factor(c("small", "large", "large", "small", "medium"))
sizes <-levels(sizes)[1] <- "L"
sizes#> [1] small L L small medium
#> Levels: L medium small
# Rename all levels at once
levels(sizes) <- c("L", "M", "S")
sizes#> [1] S L L S M
#> Levels: L M S
It’s safer to rename factor levels by name rather than by position, since you will be less likely to make a mistake (and mistakes here may be hard to detect). Also, if your input data set changes to have more or fewer levels, the numeric positions of the existing levels could change, which could cause serious but nonobvious problems for your analysis.
15.10.4 See Also
If, instead of a factor, you have a character vector with items to rename, see Recipe 15.12.