Reputation: 997
I have a data frame DF with one of the columns being date/Time and I would like to order the data frame in descending order of this column.
DF <- data.frame(ID=c('ID3', 'ID2','ID1'), end=c('4/1/10 12:00', '6/1/11 14:20', '1/1/09 11:10'), age=c(40,30,20));
I first converted the end
column into et
using et = as.POSIXct(DF$end,format='%m/%d/%Y %H:%M')
, and used the following, but got the error that unary operator '-' is not accepted for the argument :
out <- DF[order(-DF$et),];
I also tried used the descending flag but again got an error about arguments not being of same length.
out <- DF[order(DF$et, descending=TRUE),];
However, the ascending order seems to work: out <- DF[order(DF$et),]
.
How can I order in descending order (most recent time first)? Thank you.
Upvotes: 23
Views: 77348
Reputation: 389335
Using dplyr
and lubridate
-
library(dplyr)
library(lubridate)
DF %>% mutate(end = dmy_hm(end)) %>% arrange(desc(end))
# ID end age
#1 ID2 2011-01-06 14:20:00 30
#2 ID3 2010-01-04 12:00:00 40
#3 ID1 2009-01-01 11:10:00 20
If you don't want to the change the format of end
column.
DF %>% arrange(desc(dmy_hm(end)))
# ID end age
#1 ID2 6/1/11 14:20 30
#2 ID3 4/1/10 12:00 40
#3 ID1 1/1/09 11:10 20
Upvotes: 2
Reputation: 1903
There is an easy and general solution for your issue with few code.
As you have noticed, the minus sign doesn't work with Dates because negative dates don't yet exist!
However you can have the same effect with a general purpose function: rev(). Therefore, you mix rev and order like:
#init data
DF <- data.frame(ID=c('ID3', 'ID2','ID1'), end=c('4/1/10 12:00', '6/1/11 14:20', '1/1/09 11:10')
#change order
out <- DF[rev(order(as.Date(DF$end))),]
When you use the minus sign with numbers you are classing negative numbers in one pass. I think that when you use rev() function, you are doing two passes, one to sort in ascending order and one for reversing the order. But on 3 observations, it's hard to see.
Hope it helped.
Upvotes: 18
Reputation: 60000
I think this will work:
## Slightly bigger dataset with two times on same day:
DF <- data.frame(ID=c('ID3', 'ID2','ID1','ID4'), end=c('4/1/10 12:00', '6/1/11 14:20', '1/1/09 11:10' , '1/1/09 13:11'), age=c(40,30,20,20));
## Note to self - ALWAYS include a timezone.
DF$DTime <- as.POSIXct( DF$end , format = "%d/%m/%y %H:%M" , tz = "GMT")
DF[ order(DF$DTime , decreasing = TRUE ),]
# ID end age DTime
#2 ID2 6/1/11 14:20 30 2011-01-06 14:20:00
#1 ID3 4/1/10 12:00 40 2010-01-04 12:00:00
#4 ID4 1/1/09 13:11 20 2009-01-01 13:11:00
#3 ID1 1/1/09 11:10 20 2009-01-01 11:10:00
Upvotes: 11