我有一个data.table,大约有300万行和40列 . 我想按照以下sql模拟代码中的组内降序对此表进行排序:
sort by ascending Year, ascending MemberID, descending Month
在data.table中是否有相同的方法来执行此操作?到目前为止,我必须将其分解为两个步骤:
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
我现在的问题是:如果我想按年份,MemberId和sort(Year,MemberID,Month)之后的月份进行汇总,data.table是否会识别排序顺序?
更新2:回应Matthew Dowle:
在使用Year,MemberID和Month的setkey之后,每组仍然有多个记录 . 我想要的是总结每个小组 . 我的意思是:如果我使用X [order(Year,MemberID,Month)],求和是否利用data.table的二进制搜索功能:
monthly.X <- X[, lapply(.SD[], sum), by = list(Year, MemberID, Month)]
更新3:Matthew D提出了几种方法 . 第一种方法的运行时间比order()方法快:
user system elapsed
7.910 7.750 53.916
马修:让我感到惊讶的是大部分时间转换月份的标志 . 没有它,setkey的速度非常快 .
2 回答
2014年6月5日更新:
data.table v1.9.3的当前开发版本实现了两个新功能,即:
setorder
和setorderv
,它们完全符合您的要求 . 这些函数通过引用对data.table
进行重新排序,并在每个列上按顺序选择升序或降序 . 查看?setorder
了解更多信息 .此外,
DT[order(.)]
也默认优化为使用data.table
的内部快速顺序而不是base:::order
. 与setorder
不同,这将生成数据的完整副本,因此内存效率较低,但仍比使用base的顺序操作快几个数量级 .基准:
以下是使用
setorder
,data.table的内部快速订单和base:::order
的速度差异说明:在此数据上,基准测试表明data.table的订单约为 ~79x faster 而
base:::order
且setorder
是 ~135x faster ,而不是base:::order
.data.table
始终在C语言环境中排序/排序 . 如果您需要在其他语言环境中订购,那么您是否需要使用DT[base:::order(.)]
.所有这些新的优化和功能共同构成了FR #2405 . bit64::integer64 support also has been added .
评论是我的,所以我会发布答案 . 我删除它是因为我无法测试它是否与您已有的相同 . 很高兴听到它更快 .
总结不应该取决于您的行的顺序 .