Ada*_*NYC 51 performance r data.table
我有一个data.table,大约有300万行和40列.我想按照以下sql模拟代码中的组内降序对此表进行排序:
sort by ascending Year, ascending MemberID, descending Month
Run Code Online (Sandbox Code Playgroud)
在data.table中是否有相同的方法来执行此操作?到目前为止,我必须将其分解为两个步骤:
setkey(X, Year, MemberID)
Run Code Online (Sandbox Code Playgroud)
这非常快,只需几秒钟.
X <- X[,.SD[order(-Month)],by=list(Year, MemberID)]
Run Code Online (Sandbox Code Playgroud)
这个步骤需要更长的时间(5分钟).
更新:有人发表评论X <- X[sort(Year, MemberID, -Month)]并稍后删除.这种方法似乎要快得多:
user system elapsed
5.560 11.242 66.236
Run Code Online (Sandbox Code Playgroud)
我的方法:setkey()然后订购(-Month)
user system elapsed
816.144 9.648 848.798
Run Code Online (Sandbox Code Playgroud)
我现在的问题是:如果我想按年份,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)]
Run Code Online (Sandbox Code Playgroud)
更新3:Matthew D提出了几种方法.第一种方法的运行时间比order()方法快:
user system elapsed
7.910 7.750 53.916
Run Code Online (Sandbox Code Playgroud)
马修:让我感到惊讶的是大部分时间转换月份的标志.没有它,setkey的速度非常快.
Mat*_*wle 74
data.table v1.9.3的当前开发版本实现了两个新功能,即:setorder和setorderv,它完全符合您的要求.这些函数data.table 按引用重新排序,并在每个列上按顺序选择升序或降序.查看?setorder更多信息.
此外,DT[order(.)]还通过优化默认使用data.table的内部快速为了代替base:::order.与此不同的是setorder,它将生成数据的完整副本,因此内存效率较低,但仍比使用base的顺序操作快几个数量级.
以下是使用setorderdata.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
Run Code Online (Sandbox Code Playgroud)
这一数据,基准表明,data.table的订单约为〜79x速度比base:::order和setorder是〜135x速度比base:::order在这里.
data.table总是在C语言环境中排序/订单.如果您需要在其他语言环境中订购,那么您是否需要求助于使用DT[base:::order(.)].
所有这些新的优化和功能共同构成FR#2405.bit64 :: integer64支持也已添加.
注意:请参阅早期答案和更新的历史记录/修订版.
Mat*_*rde 13
评论是我的,所以我会发布答案.我删除它是因为我无法测试它是否与您已有的相同.很高兴听到它更快.
X <- X[order(Year, MemberID, -Month)]
Run Code Online (Sandbox Code Playgroud)
总结不应该取决于您的行的顺序.