Written and maintained by CASRAI Editorial Board
Last updated
To rename columns in R, use rename(df, new_name = old_name) from the dplyr package for one or a few columns, rename_with(df, .fn) to apply a function such as toupper to many names at once, or base R’s names(df) <- c(...) to replace every name in one step. This page also covers what happens when a name is missing or the replacement list is the wrong length.
What it is used for in research
Raw exports from survey platforms, instruments and spreadsheets rarely arrive with analysis-ready column names. They may contain spaces, mixed case or abbreviations that are awkward to type in code. Renaming in a script, rather than editing the file by hand, leaves a written record of every change between the raw data and the analysed data, which is a basic ingredient of computational reproducibility. If you are working with the structure that holds these columns, see data frames in R; if you are moving between languages, the equivalent task in Python is covered in renaming columns in a pandas DataFrame.
Install or access
Base R’s names() and colnames() ship with R itself, so nothing needs installing. rename() and rename_with() belong to dplyr, which the dplyr project site describes as available in two ways:
# The easiest way to get dplyr is to install the whole tidyverse:
install.packages("tidyverse")
# Alternatively, install just dplyr:
install.packages("dplyr")
Then load it once per session with library(dplyr). The examples below use the iris data frame that is built into R, whose columns are Sepal.Length, Sepal.Width, Petal.Length, Petal.Width and Species.
Step-by-step: rename one column, several columns, or all of them
1. Rename one or several columns with rename()
The dplyr reference gives the usage as rename(.data, ...) and states that rename() changes the names of individual variables using new_name = old_name syntax. The new name goes on the left, which is the reverse of what many people expect.
library(dplyr)
rename(iris, petal_length = Petal.Length)
To rename several columns, add more new_name = old_name pairs separated by commas in the same call. Assign the result back (iris2 <- rename(iris, ...)) if you want to keep it, because rename() returns a data frame with the new names rather than changing the original object in place.
2. Rename from a lookup vector with all_of() or any_of()
When the old and new names live in a named vector, for example a data dictionary you maintain, the dplyr reference shows this pattern:
lookup <- c(pl = "Petal.Length", sl = "Sepal.Length")
rename(iris, all_of(lookup))
rename(iris, any_of(lookup))
The two helpers differ only when a name in the lookup is absent from the data. According to the reference, all_of() raises an error if a name is missing, while any_of() skips the missing names; the reference advises any_of() “if your named vector might contain names that don’t exist in the data”. Use all_of() when a missing column should stop the script (the safer default for a fixed analysis), and any_of() when the same lookup is reused across files that do not all contain every column.
3. Rename many columns with rename_with()
The usage is rename_with(.data, .fn, .cols = everything(), ...). Instead of naming each column, you supply a function that takes the selected column names and returns new ones. Per the reference, .fn must return a character vector of the same length as its input, and .cols accepts tidy-select helpers, defaulting to every column. Examples from the reference:
rename_with(iris, toupper)
rename_with(iris, toupper, starts_with("Petal"))
rename_with(iris, ~ tolower(gsub(".", "_", .x, fixed = TRUE)))
The first upper-cases every name, the second only the columns whose names start with “Petal”, and the third turns dots into underscores and lower-cases the result, a common clean-up because dots in names are awkward in later code.
4. Rename in base R with names() or colnames()
Base R needs no package. For a data frame, the base documentation says that rownames and colnames eventually call row.names and names respectively, but that the latter are preferred, so names() is the documented first choice:
names(iris) <- c("sl", "sw", "pl", "pw", "species") # replace all names, in column order
names(iris)[names(iris) == "Species"] <- "species" # replace one name by matching it
names(iris)[2] <- "sepal_width" # replace one name by position
The colnames(x) <- value form is documented for matrix-like objects with at least two dimensions; value must be NULL or a character vector whose length matches the dimension, and values are coerced with as.character. Because the assignment is positional, supplying names in the wrong order renames the wrong columns without any warning, so the matching form on the second line above is safer when you only want to change one column.
Output and how to read it
After rename(iris, petal_length = Petal.Length) the returned data frame has the same rows and the same column order; only the third column’s name has changed, so names(...) on the result reads "Sepal.Length" "Sepal.Width" "petal_length" "Petal.Width" "Species". Check any rename with names(df) or colnames(df) straight afterwards, and again after joins or imports, since later steps in a pipeline may depend on the new names.
Troubleshooting
A rename fails because a column name is missing
If you built the renaming from all_of(), an absent name is an error by design. Check the spelling and case against names(df), or switch to any_of() if absent columns are expected.
Replacing all names with the wrong number of values
Supply exactly one new name per column. The base documentation requires the replacement vector’s length to match the dimension, so count with ncol(df) first.
rename_with() errors on an empty selection when using paste0()
The dplyr reference says that if your renaming function uses paste0(), you should set recycle0 = TRUE; otherwise a selection that matches no columns produces an error about the length of the returned vector.
Free alternatives
| Approach | Where it comes from | Use it when |
|---|---|---|
rename() |
dplyr (also installed with the tidyverse) | You know the old and new names, or hold them in a lookup vector |
rename_with() |
dplyr | You want a rule (case, separators, prefixes) applied to many or all names |
names() / colnames() |
Base R, no package | You want to replace every name at once, or avoid a dependency |
FAQ
How do I rename a column by its position?
Use base R: names(df)[2] <- "new_name" changes the second column’s name and leaves the rest alone.
How do I rename multiple columns at once?
With dplyr, list several new_name = old_name pairs in one rename() call, or pass a named lookup vector inside all_of() or any_of(). With base R, assign a full character vector to names(df).
How do I make all column names lowercase?
rename_with(df, tolower). The dplyr reference demonstrates the same pattern with toupper.
What is the difference between rename() and rename_with()?
rename() changes names you specify one by one; rename_with() applies one function to a set of names chosen with tidy-select helpers.
Sources
- dplyr reference, “Rename columns”: https://dplyr.tidyverse.org/reference/rename.html (checked 2026-10-29)
- dplyr installation instructions: https://dplyr.tidyverse.org/ (checked 2026-10-29)
- R base documentation, “Row and Column Names”: https://stat.ethz.ch/R-manual/R-devel/library/base/html/colnames.html (checked 2026-10-29)
Related on CASRAI: transposing a data frame in R.







