【问题标题】:How to order data within subgroups in data.table R如何在 data.table R 的子组中对数据进行排序
【发布时间】:2015-02-23 21:23:14
【问题描述】:

考虑以下几点:

DT = data.table(a=sample(1:2), b=sample(1:1000,20))

如何按每个 a 显示 b,例如 n 个最高值?

我被困在DT[,b,by=a][order(a,-b)]

谢谢!

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    最优雅的应该是:

    DT[order(-b),head(b,5),by=a]
    

    就纯粹的性能而言:

    DT[order(-b), indx := seq_len(.N), "a"][indx <= 5][,indx:=NULL][]
    

    或者@Frank 建议的那个:

    DT[DT[order(-b),.I[1:.N<=5],"a"]$V1]
    

    低于以上所有三个的基准:

    # devtools::install_github("jangorecki/dwtools")
    library(dwtools) # to populate complex dataset
    N <- 5e6
    DT <- dw.populate(N, scenario="fact")
    str(DT)
    #Classes ‘data.table’ and 'data.frame': 5000000 obs. of  8 variables:
    # $ cust_code: chr  "id010" "id076" "id024" "id081" ...
    # $ prod_code: int  8234 5689 31198 35479 39140 37589 8184 39489 35266 3596 ...
    # $ geog_code: chr  "OH" "NH" "TN" "MI" ...
    # $ time_code: Date, format: "2012-03-11" "2014-02-10" "2012-11-05" "2013-01-30" ...
    # $ curr_code: chr  "XRP" "HRK" "CAD" "BRL" ...
    # $ amount   : num  486 382 695 470 749 ...
    # $ value    : num  193454 33694 351418 84888 20673 ...
    

    cust_code列,uniqueN等于100:

    system.time(DT[order(-time_code),head(.SD,5),"cust_code"])
    #   user  system elapsed 
    #  1.804   0.084   1.890 
    system.time(DT[order(-time_code), indx := seq_len(.N),"cust_code"][indx <= 5][,indx:=NULL][])
    #   user  system elapsed 
    #  1.414   0.092   1.508 
    system.time(DT[DT[order(-time_code),.I[1:.N<=5],"cust_code"]$V1])
    #   user  system elapsed 
    #  1.405   0.096   1.502 
    

    如果有更多的组(prod_code 列,uniqueN 等于 50000),那么我们可以看到对性能的影响:

    system.time(DT[order(time_code),head(.SD,5),"prod_code"])
    #   user  system elapsed 
    # 10.177   0.109  10.322
    system.time(DT[order(time_code), indx := seq_len(.N),"prod_code"][indx <= 5][,indx:=NULL][])
    #   user  system elapsed 
    #  1.555   0.099   1.665 
    system.time(DT[DT[order(time_code),.I[1:.N<=5],"prod_code"]$V1])
    #   user  system elapsed 
    #  1.697   0.064   1.764
    

    2015-11-09 更新:

    对于今天的 Arun 提交 e615532headtail 应该在底层进行优化。

    【讨论】:

    • 我不知道为什么第二种方法应该更快。相对于制作1:.N,为每个a(传递给head)复制b 成本高吗?我看到最终结果仍然不是“每个a”每个OP...如果有加速,我敢打赌这也会做到:DT[DT[order(-b),.I[1:.N&lt;=5],"a"]$V1] ...从@987654322复制@
    • 使用@Frank 代替head 我认为会显着加快第一个版本,因为它将避免head 进行的各种检查。
    • @Frank,我已经添加了基准测试,这三种解决方案似乎没有太大区别。无论如何,很大程度上取决于数据集。
    • 更新:刚刚为更多组添加了基准,现在很明显第一个解决方案要慢得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 1970-01-01
    • 2017-12-23
    相关资源
    最近更新 更多