colnames()
colnames(x) <- value colnames() retrieves or sets the column names of matrices, data frames, and array-like objects. They are essential for working with tabular data and are the column equivalent of rownames() for rows.
Syntax
# Get column names
colnames(x)
# Set column names
colnames(x) <- value
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
x | matrix, data.frame, or array | , | The object whose column names to get or set |
value | character vector or NULL | , | New column names to assign |
Examples
Basic usage
df <- data.frame(
name = c("Alice", "Bob", "Carol"),
age = c(25, 30, 35),
score = c(85, 92, 78)
)
colnames(df)
# [1] "name" "age" "score"
The returned character vector gives you the current column names in their existing order. This makes colnames() a discovery tool when you inherit a dataset from another script and need to confirm what columns are available. Knowing the names lets you reference columns by name rather than position, so your code stays readable even when the data structure changes.
Setting column names
colnames(df) <- c("Name", "Age", "Score")
df
# Name Age Score
# 1 Alice 25 85
# 2 Bob 30 92
# 3 Carol 35 78
Assigning a character vector to colnames(df) replaces every column name at once. The length of the replacement vector must match the number of columns exactly, otherwise R raises an error. For renaming only one or two columns, index with bracket notation instead of reassigning the whole vector.
Working with matrices
mat <- matrix(1:9, nrow = 3, ncol = 3)
colnames(mat) <- c("A", "B", "C")
mat
# A B C
# 1 1 4 7
# 2 2 5 8
# 3 3 6 9
Matrices use dimnames under the hood, and colnames() is the conventional accessor for the second dimension. For data frames, names(df) returns the same result as colnames(df), but on matrices names() returns NULL while colnames() returns the column names correctly, so always prefer colnames() when working with matrix objects.
Common patterns
Subset by column name:
df[, "age"]
# [1] 25 30 35
Bracket-based column selection with a character string is the base R equivalent of dplyr::select(). The double-bracket form df[["age"]] returns a vector, while single-bracket df["age"] returns a one-column data frame. Which one you pick depends on whether downstream code expects a vector or a data frame.
Check if column exists:
"score" %in% colnames(df)
# [1] TRUE
The %in% operator tests each element of the left vector for membership in the right vector, returning a logical vector the same length as the left side. This pattern generalizes to checking multiple column names at once: c("score", "grade") %in% colnames(df) confirms which of the requested columns actually exist in the data.
Rename specific columns:
colnames(df)[colnames(df) == "score"] <- "final_score"
colnames() and rownames() in practice
colnames() returns or sets the column names of a matrix or data frame. colnames(df) is equivalent to names(df) for data frames, both access the same underlying names attribute. For matrices, colnames() is the appropriate accessor since names() on a matrix returns NULL (matrices use dimnames rather than names).
Setting column names: colnames(df) <- c("x", "y", "z") renames all columns at once. For renaming a subset, use colnames(df)[2] <- "new_name" or dplyr::rename(). The setnames() function from the data.table package renames columns by reference (without copying) for large data frames.
colnames() and rownames() are the matrix-specific versions of names(). Both get and set the respective dimension names from dimnames(m): dimnames(m)[[1]] for row names and dimnames(m)[[2]] for column names. Setting them to NULL removes the names. All three functions are generic and dispatch on class.
For checking whether specific column names exist, "col" %in% colnames(df) returns TRUE if the column exists. setdiff(required_cols, colnames(df)) returns any required columns that are missing, a pattern for input validation in data processing functions.
colnames() gets or sets column names on a matrix or data frame. It is equivalent to names() for data frames but more explicit. Setting colnames(m)[2] <- "new" renames only the second column without affecting others. For data frames in tidyverse pipelines, rename() is preferred because it works by name rather than position. make.names() converts arbitrary strings to valid R identifiers, useful after reading data with non-standard column names.
colnames() gets or sets column names on a matrix or data frame. For data frames, it is equivalent to names(). Setting a single column name by index, colnames(m)[2] <- "new_name" — avoids overwriting all other names. For vectors, colnames() returns NULL; use names() for named vectors.
When column names contain special characters or spaces, they must be quoted with backticks in R code: df\my col`. make.names(names(df), unique = TRUE)` sanitizes names to valid R identifiers and ensures uniqueness — useful after reading data from CSV files or databases where column names may include spaces, leading digits, or special characters.
colnames() on a tibble returns a character vector. Reassigning names with colnames(tbl) <- new_names works but may have unintended effects on tbl_df metadata — prefer rename() or rename_with() in tidyverse workflows for predictable behavior.
dimnames(m)[[2]] is the lower-level accessor that colnames() wraps. Both are equivalent; colnames() is the conventional choice for readability.
Renaming columns with regular expressions
When column names follow a predictable pattern, gsub() combined with colnames() renames them all at once without manually typing each new name:
# Raw column names with inconsistent prefixes
raw <- c("X2021_sales", "X2021_costs", "X2022_sales", "X2022_costs")
df <- setNames(data.frame(1:10, 2:11, 3:12, 4:13), raw)
# Strip the year prefix and keep the metric name
colnames(df) <- gsub("^X\\d{4}_", "", colnames(df))
colnames(df)
# [1] "sales" "costs" "sales" "costs"
# Make unique after stripping
colnames(df) <- make.names(colnames(df), unique = TRUE)
colnames(df)
# [1] "sales" "costs" "sales.1" "costs.1"
The combination of gsub() for pattern replacement and make.names() for uniqueness guarantees gives you clean, valid column names even when the original headers are messy. This pattern is especially common after importing CSV files exported from spreadsheets, where column headers often carry date stamps or workspace prefixes that you want to strip before analysis.
Validating required columns in a function
A defensive programming pattern uses colnames() to check that a data frame contains the columns a function expects:
validate_cols <- function(df, required) {
missing <- setdiff(required, colnames(df))
if (length(missing) > 0) {
stop("Missing columns: ", paste(missing, collapse = ", "))
}
invisible(TRUE)
}
test_df <- data.frame(x = 1:3, y = 4:6)
validate_cols(test_df, c("x", "y", "z"))
# Error: Missing columns: z
This pattern catches structural problems early, before the function attempts operations on columns that do not exist. Wrapping it in a standalone validator makes the intent explicit in the code and reusable across multiple functions that share the same column requirements.