Skip to content

WISH: deprecate data.frame(..., row.names = "name of column to use as rownames") and add explicit alternative #173

Description

@jan-glx

Currently, data.frame provides and argument row.names that not only allows for supplying row names to be used for the new data frame but also allows for specifying a column whose values to use as row names:

row.names NULL or a single integer or character string specifying a column to be used as row names, or a character or integer vector giving the row names for the data frame.

However, in the case of a single row data frame, there is no way to distinguish these two meanings, leading to inconsistent behavior:

data.frame(id=paste0("row", 1:2), val=1:2) |> data.frame(row.names="id")
#      val
# row1   1
# row2   2
data.frame(id=paste0("row", 1:1), val=1:1) |> data.frame(row.names="id")
#      id val
# id row1   1

To prevent the resulting edge-case bugs, developers have to avoid this feature and instead use code such as rownames(df) <- df$id; df$id <- NULL. or :

 col_as_rownames <- function(data, col.as.row.names) {
    stopifnot(length(col.as.row.names)==1)
    idx <- if(is.numeric(col.as.row.names)) col.as.row.names else which(colnames(data) == col.as.row.names)
    data.frame(data[, -idx, drop = FALSE], row.names=data[, idx])
}
data.frame(id=paste0("row", 1:2), val=1:2) |> col_as_rownames("id")
data.frame(id=paste0("row", 1:1), val=1:1)  |> col_as_rownames("id")
  • ?base::data.frame should be updated to caution against using row.names with a column name or index and point to an safe alternative
  • base::data.frame should provide an argument col.as.row.names or so to achieve the same in a simple and safe way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions