当前位置: 首页 > 知识库问答 >
问题:

对数据进行排序。表按升序/降序快速

祝花蜂
2023-03-14

我有数据。表中有大约300万行和40列。我希望在组内按降序对该表排序,如以下sql模拟代码:

sort by ascending Year, ascending MemberID, descending Month 

数据中是否存在等效的方法。这张桌子可以吗?到目前为止,我必须将其分解为两个步骤:

setkey(X, Year, MemberID)

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

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

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

更新:有人评论要执行<code>X

user  system elapsed 
5.560  11.242  66.236 

我的方法是:setkey()然后是order(-Month)

   user  system elapsed 
816.144   9.648 848.798 

我现在的问题是:如果我想按年、MemberId和一个又一个排序(年、MemberID、月)进行汇总,data.table识别排序顺序吗?

更新2:回应马修·道尔:

在用Year、MemberID和Month设置了setkey之后,我仍然有每组多条记录。我想对每个小组进行总结。我的意思是:如果我使用X[order(Year,MemberID,Month)],求和是否利用了数据的二分搜索法函数。表:

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

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

   user  system elapsed 
  7.910   7.750  53.916 

马修:让我惊讶的是,转换月份符号花费了大部分时间。没有它,setkey的速度很快。

共有2个答案

赵明亮
2023-03-14

评论是我的,所以我会把答案贴上来。我删除它是因为我无法测试它是否与您已经拥有的内容等效。很高兴听到它更快。

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

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

唐海阳
2023-03-14

data.tablev1.9.3的当前开发版本实现了两个新函数,即:setordersetorderv,它完全满足您的要求。这些函数通过引用重新排序data.table,并在每个要排序的列上选择升序或降序。查看? setorder以获取更多信息。

此外,默认情况下,DT[订单(.)] 也经过优化,以使用 data.table 的内部快速顺序,而不是基数:::顺序。与设定顺序不同,这将制作数据的整个副本,因此内存效率较低,但仍比使用基序操作快几个数量级。

下面是使用< code>setorder、data.table的内部快速顺序和< code>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

根据这一数据,基准表明了这一数据。表的顺序大约比基:::order快约79倍,setorderbase::order这里快约135倍。

< code>data.table总是在C语言环境中排序。如果您需要在另一个地区订购,那么您只需要使用< code>DT[base:::order(.)]。

所有这些新的优化和功能一起构成了FR#2405。位64::整数64支持也已添加。

注:请参阅历史记录/修订,了解早期答案和更新。

 类似资料:
  • 我想按第三个和第一个元素对元组数组进行排序,因此我使用了以下代码: 我的问题是,在前面的例子中,我可以按第三个元素和第一个元素的升序排序,也可以按它们的降序排序(使用反向)。但是如何按第三个元素的升序和第一个元素的降序排序。 请在你的回答中考虑以下情况: 在这种情况下,我不知道内部数组的确切大小(取决于我读入该数组的文件模式),我想按侧中的所有项进行排序(一些升序和一些降序)。 编辑:看起来,我明

  • 我有一个通用的链表,目前由int组成,我想在默认情况下按升序排序,然后切换一个布尔值,按降序排序。我该怎么做?

  • 考虑下面的哈希图: 具有诸如 我需要按值对hashmap进行降序排序,但如果值相等,则按键进行升序排序: 到目前为止,我试着分别按键排序,然后按值排序,但我不相信这种方法。除了创建更多的hashmaps之外,还有什么好方法呢?

  • 有人能提供帮助,如何检查排序降序数组以及?干杯!

  • 问题内容: 我将应用程序发布的想法存储在Firestore中。数据像这个 Ideas / {documentID} / IdeaObject 一样存储在Firestore中。问题是,当我检索数据时,它没有按发布时间排序。检索到的构想根据其文档ID的ID来确定,该ID由Firestore自动创建。我在模型类中使用了 ServerTimestamp ,并且在检索它时,我在Firestore引用中使用了