175

I would like to convert the values in a column of an existing data frame into row names. Is is possible to do this without exporting the data frame and then reimporting it with a row.names = call?

For example I would like to convert:

 > samp 
     names Var.1 Var.2 Var.3
 1     A     1     5     0
 2     B     2     4     1
 3     C     3     3     2
 4     D     4     2     3
 5     E     5     1     4

Into:

> samp.with.rownames 
     Var.1 Var.2 Var.3
A     1     5     0
B     2     4     1
C     3     3     2
D     4     2     3
E     5     1     4

5 Answers 5

186

This should do:

samp2 <- samp[,-1]
rownames(samp2) <- samp[,1]

So in short, no there is no alternative to reassigning.

Edit: Correcting myself, one can also do it in place: assign rowname attributes, then remove column:

R> df<-data.frame(a=letters[1:10], b=1:10, c=LETTERS[1:10])
R> rownames(df) <- df[,1]
R> df[,1] <- NULL
R> df
   b c
a  1 A
b  2 B
c  3 C
d  4 D
e  5 E
f  6 F
g  7 G
h  8 H
i  9 I
j 10 J
R> 
Sign up to request clarification or add additional context in comments.

2 Comments

> rownames(df)<-df[,1] Error in row.names<-.data.frame(*tmp*, value = value) : invalid 'row.names' length In addition: Warning message: Setting row names on a tibble is deprecated.
@user3673 A likely suspect is that you are not working with a dataframe. Verify this via class(df). If this gives multiple classes, simply call df<- as.data.frame(df) that should resolve it.
103

As of 2016 you can also use the tidyverse.

library(tidyverse)
samp %>% remove_rownames %>% column_to_rownames(var="names")

4 Comments

More specifically, it is tibble::column_to_rownames
I get a warning "Setting row names on a tibble is deprecated"
tibble visualization doesn't show rownames, though, to see it you need to pipe it to as.data.frame() samp %>% remove_rownames %>% column_to_rownames(var="names") %>% as.data.frame()
It looks like the latest version of the package automatically handles the conversion from tibble to data.frame.
29

in one line

> samp.with.rownames <- data.frame(samp[,-1], row.names=samp[,1])

Comments

27

It looks like the one-liner got even simpler along the line (currently using R 3.5.3):

# generate original data.frame
df <- data.frame(a = letters[1:10], b = 1:10, c = LETTERS[1:10])
# use first column for row names
df <- data.frame(df, row.names = 1)

The column used for row names is removed automatically.

With a one-row dataframe

Beware that if the dataframe has a single row, the behaviour might be confusing. As the documentation mentions:

If row names are supplied of length one and the data frame has a single row, the row.names is taken to specify the row names and not a column (by name or number).

This mean that, if you use the same command as above, it might look like it did nothing (when it actually named the first row "1", which won't look any different in the viewer).

In that case, you will have to stick to the more verbose:

df <- data.frame(a = "a", b = 1)
df <- data.frame(df, row.names = df[,1])

... but the column won't be removed. Also remember that, if you remove a column to end up with a single-column dataframe, R will simplify it to an atomic vector. In that case, you will want to use the extra drop argument:

df <- data.frame(df[,-1, drop = FALSE], row.names = df[,1])

1 Comment

Neat! I went straight for the tidyverse solution without checking to see if base R had a handy way of dealing with the issue. I should start with base.
14

You can execute this in 2 simple statements:

row.names(samp) <- samp$names
samp[1] <- NULL

1 Comment

Works in R 3.5.3

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.