按升序/降序快速sortingdata.table

我有一个约300万行和40列data.table。 我想按照下面的SQL模拟代码按照降序sorting这个表:

sort by ascending Year, ascending MemberID, descending Month 

data.table中有一个等价的方法来做到这一点? 到目前为止,我必须将其分解成2个步骤:

 setkey(X, Year, MemberID) 

这是非常快的,只需要几秒钟。

 X <- X[,.SD[order(-Month)],by=list(Year, MemberID)] 

这一步需要更长的时间(5分钟)。

更新:有人发表评论做X <- X[sort(Year, MemberID, -Month)] ,后来被删除。 这种方法似乎要快得多:

 user system elapsed 5.560 11.242 66.236 

我的方法:setkey()然后命令(-Month)

  user system elapsed 816.144 9.648 848.798 

我现在的问题是:如果我想在Year,MemberId和Month(Year,MemberID,Month)之后进行总结,data.table是否能识别sorting顺序?

更新2:回应Matthew Dowle:

设置Year,MemberID和Month后,我仍然有多组logging。 我想要对每个组进行总结。 我的意思是:如果我使用X [order(Year,MemberID,Month)],求和是否利用data.table的二进制searchfunction:

 monthly.X <- X[, lapply(.SD[], sum), by = list(Year, MemberID, Month)] 

更新3:马修D提出了几种方法。 第一种方法的运行时间比order()方法快:

  user system elapsed 7.910 7.750 53.916 

马修:令我感到吃惊的是,大部分时间里,月份的标志转换。 没有它,setkey是快速的。

2014年6月5日更新:

data.table v1.9.3目前的开发版本实现了两个新的function,即: setordersetorderv ,它正是你所需要的。 这些函数通过引用data.table 进行重新sorting,select每个列上的升序或降序来sorting。 退房?setorder了解更多信息。

另外, DT[order(.)]也默认优化为使用data.table内部快速顺序,而不是base:::order 。 与setorder不同的setorder ,这将完成数据的整个拷贝,因此内存效率更低,但仍将比使用基本的订单快setorder数量级。

基准:

下面是使用setorder ,data.table的内部快速命令和base:::order的速度差异说明:

 require(data.table) ## 1.9.3 set.seed(1L) DT <- data.table(Year = sample(1950:2000, 3e6, TRUE), memberID = sample(paste0("V", 1:1e4), 3e6, TRUE), month = sample(12, 3e6, TRUE)) ## using base:::order system.time(ans1 <- DT[base:::order(Year, memberID, -month)]) # user system elapsed # 76.909 0.262 81.266 ## optimised to use data.table's fast order system.time(ans2 <- DT[order(Year, memberID, -month)]) # user system elapsed # 0.985 0.030 1.027 ## reorders by reference system.time(setorder(DT, Year, memberID, -month)) # user system elapsed # 0.585 0.013 0.600 ## or alternatively ## setorderv(DT, c("Year", "memberID", "month"), c(1,1,-1)) ## are they equal? identical(ans2, DT) # [1] TRUE identical(ans1, ans2) # [1] TRUE 

在这个数据上,基准表明data.table的顺序比base:::order 大约79倍setorderbase:::order 快135x

data.table总是在C语言环境中sorting/sorting。 如果你需要在另一个地方订购,那么你需要使用DT[base:::order(.)]

所有这些新的优化和function一起构成FR#2405 。 bit64 :: integer64支持也被添加了 。


注意:请参阅历史logging/修订以获取更早的答案和更新。

评论是我的,所以我会发布答案。 我删除了它,因为我无法testing它是否与您已有的相同。 很高兴听到它更快。

 X <- X[order(Year, MemberID, -Month)] 

总结不应取决于您的行的顺序。