Reputation: 1325
I have a data.frame like this:
id<-c("001-020", "001-010", "001-051")
name<-c("Fred", "Sue", "Liam")
df<-data.frame(id, name)
I tried:
df[with(df, order(id)), ]
# id name
# 2 001-010 Sue
# 1 001-020 Fred
# 3 001-051 Liam
which orders the data.frame correctly, but doesn't touch the rownames.
How may I reorder the data.frame using the ascending order of the id field and rewrite the rownames in one go?
Upvotes: 3
Views: 3004
Reputation: 35314
Since row names are stored as an attribute on the object, perhaps structure()
would be appropriate here:
structure(df[order(df$id),],row.names=rownames(df));
## id name
## 1 001-010 Sue
## 2 001-020 Fred
## 3 001-051 Liam
Upvotes: 1
Reputation: 887038
You could try
newdf <- df[with(df, order(id)), ]
row.names(newdf) <- NULL
Or it can be done in a single step
newdf <- `row.names<-`(df[with(df,order(id)),], NULL)
Setting row.names
to NULL
will also work when you have an empty data.frame.
d1 <- data.frame()
row.names(d1) <- NULL
d1
#data frame with 0 columns and 0 rows
If we do the same with 1:nrow
row.names(d1) <-1:nrow(d1)
#Error in `row.names<-.data.frame`(`*tmp*`, value = c(1L, 0L)) :
#invalid 'row.names' length
Or another option is data.table
library(data.table)#v1.9.4+
setorder(setDT(df), id)[]
Or
setDT(df)[order(id)]
Or using sqldf
library(sqldf)
sqldf('select * from df
order by id')
Upvotes: 8
Reputation: 31161
I am surprised it's not in the previous answers.
What you are looking for is arrange
from plyr
:
library(plyr)
arrange(df, id)
# id name
#1 001-010 Sue
#2 001-020 Fred
#3 001-051 Liam
Upvotes: 3
Reputation: 330073
You can simply assign new rownames
:
df2 <- df[with(df, order(id)), ]
rownames(df2) <- 1:nrow(df2)
And a cleaner solution with magrittr
:
library(magrittr)
df %>% extract(order(df$id), ) %>% set_rownames(1:nrow(df))
Upvotes: 4