rguides

rownames()

rownames(x) <- value

rownames() retrieves or sets the row names of matrices, data frames, and array-like objects. They are essential for working with tabular data and are the row equivalent of colnames() for columns.

Syntax

# Get row names
rownames(x)

# Set row names
rownames(x) <- value

Parameters

ParameterTypeDefaultDescription
xmatrix, data.frame, or array,The object whose row names to get or set
valuecharacter vector or NULLNew row names to assign

Examples

Basic usage

# Create a simple data frame
df <- data.frame(
  name = c("Alice", "Bob", "Carol"),
  age = c(25, 30, 35),
  score = c(85, 92, 78)
)

# Get row names (defaults to NULL for data frames)
rownames(df)
# [1] "1" "2" "3"

When no explicit row names are set, rownames() returns character representations of the row indices: "1", "2", "3", and so on. These default names are generated by as.character(seq_len(nrow(x))) and are stored as an attribute on the data frame. They are not meaningful identifiers — they simply mirror the row position — and they become misleading after any operation that reorders, filters, or subsets the data frame.

Setting row names

# Set row names
rownames(df) <- c("row_1", "row_2", "row_3")
df
#       name age score
# row_1 Alice  25     85
# row_2   Bob  30     92
# row_3 Carol  35     78

Assigning row names replaces the default numeric identifiers with meaningful labels, which enables row-by-name subsetting with df["row_1", ]. The row names must be unique — duplicates raise an error. When you later filter or reorder the data frame, the row names travel with their rows, so df[3:1, ] reverses the row order and the associated names reverse with them, preserving the name-to-data association.

Working with matrices

# Create a matrix
mat <- matrix(1:9, nrow = 3, ncol = 3)
rownames(mat) <- c("x", "y", "z")
mat
#   [,1] [,2] [,3]
# x    1    4    7
# y    2    5    8
# z    3    6    9

Matrices store row and column names together in a dimnames attribute — a list of length 2 where the first element holds row names and the second holds column names. rownames() and colnames() are convenience accessors that read and write the corresponding elements of this list. Setting row names on a matrix to a vector of the wrong length raises an error, since the number of names must exactly match the number of rows.

Common patterns

Subset by row name:

df["row_1", ]
#   name age score
# 1 Alice  25     85

Row-by-name subsetting with df["row_1", ] returns a data frame row as a new data frame, not a vector. To extract a single row as a named vector, use df["row_1", , drop = TRUE] or unlist(df["row_1", ]). This distinction matters when you expect a vector result for further computation — forgetting drop = TRUE is a common source of type-related bugs in base R row-extraction code.

Check if row exists:

"row_1" %in% rownames(df)
# [1] TRUE

rownames() in practice

rownames() returns or sets the row names of a matrix or data frame. For a freshly created data frame, rownames(df) returns character representations of the row indices: "1", "2", "3", etc. These default numeric row names are not meaningful and can be confusing when they desync from actual row numbers after filtering or reordering.

After filtering or subsetting, row names retain their original values: df[df$x > 0, ] returns a data frame with row names "3", "5", "7" (the original indices of the matching rows). Reset with rownames(df) <- NULL or row.names(df) <- NULL after subsetting to get clean sequential names. tibble avoids this confusion entirely by never using meaningful row names.

Setting row names: rownames(df) <- df$id sets the ID column as row names, enabling row-by-name access: df["user123", ]. This pattern comes from base R workflows but is less common in tidyverse code, where explicit key columns are preferred.

For matrices, rownames() and colnames() are both accessed via dimnames(m)[[1]] and dimnames(m)[[2]] respectively. rownames(m) and colnames(m) are convenience wrappers. Setting either to a character vector of the wrong length raises an error.

rownames() gets or sets row names on a matrix or data frame. Unlike column names, row names are not used for data operations in most tidyverse functions — tibbles do not support meaningful row names and will coerce them to a column if present. In base R, row names default to character representations of sequential integers: "1", "2", etc. Setting rownames(df) <- NULL resets them to the default sequence.

See also

  • class()
  • colnames()
  • sample() tibble::rownames_to_column(df, 'id') converts row names to a regular column before converting to tibble.tibbles do not support meaningful row names — when you convert a data frame with row names to a tibble with as_tibble(), the row names are silently dropped. To preserve row names as a column: as_tibble(df, rownames = "name"). rownames_to_column(df, "name") from tibble package does the same. For matrices, row names are displayed in printed output and used by [ subscripting with strings: m["row1", ] selects the row named “row1”.