【问题标题】:How to subset data.table using keys [duplicate]如何使用键对data.table进行子集化[重复]
【发布时间】:2019-09-16 20:29:18
【问题描述】:

我有一个 data.table,我正在尝试对其进行子集化,以便通过 ID 和 LAB_DT 获得最低的 TEST_RESULT:

DT <- data.table::data.table(ID=c("1","1","1","2","2","3","3","3"),
                             LAB_DT=lubridate::as_date(c("1992-11-01",
                                                         "1992-11-01",
                                                         "1992-11-02",
                                                         "1992-11-04",
                                                         "1992-11-04",
                                                         "1992-11-06",
                                                         "1992-11-06",
                                                         "1992-11-08")),
                             TEST_RESULT=c(5.4,5.8,5.2,5.6,6,6,7,8))
setkeyv(DT,c("ID","LAB_DT","TEST_RESULT"))

   ID     LAB_DT TEST_RESULT
1:  1 1992-11-01         5.4
2:  1 1992-11-01         5.8
3:  1 1992-11-02         5.2
4:  2 1992-11-04         5.6
5:  2 1992-11-04         6.0
6:  3 1992-11-06         6.0
7:  3 1992-11-06         7.0
8:  3 1992-11-08         8.0

我已经通过自己的方法成功做到了:

DT[,FIRST.LAB_DT:=0]
DT[, FIRST.LAB_DT := c(1L, FIRST.LAB_DT[-1]), by = .(ID,LAB_DT)]

   ID     LAB_DT TEST_RESULT FIRST.LAB_DT
1:  1 1992-11-01         5.4            1
2:  1 1992-11-01         5.8            0
3:  1 1992-11-02         5.2            1
4:  2 1992-11-04         5.6            1
5:  2 1992-11-04         6.0            0
6:  3 1992-11-06         6.0            1
7:  3 1992-11-06         7.0            0
8:  3 1992-11-08         8.0            1

DT[FIRST.LAB_DT==1,]

   ID     LAB_DT TEST_RESULT FIRST.LAB_DT
1:  1 1992-11-01         5.4            1
2:  1 1992-11-02         5.2            1
3:  2 1992-11-04         5.6            1
4:  3 1992-11-06         6.0            1
5:  3 1992-11-08         8.0            1

但是,我正在使用的实际 data.table 有 ~8e6 行和I recently found,您可以使用键以更快的方式对 data.table 进行子集化。

有人知道如何使用键产生相同的最终输出吗?

【问题讨论】:

  • 与key无关,但我认为这将是获得结果的最快方法:DT[DT[, .I[which.min(TEST_RESULT)], .(ID, LAB_DT)]$V1]
  • @IceCreamToucan 我排在第二位,是最快的。我认为 hadley 提出了这个问题,询问data.table 中子集的性能,并且对该线程进行了很好的讨论/回答。我看看能不能找到。 p.s.已经找到了。

标签: r data.table key subset


【解决方案1】:

由于您报告您当前的方法有效,因此您的数据显然已经通过增加 TEST_RESULT 进行排序。在这种情况下,您可以删除重复项以保留每个组的第一行:

unique(DT, by=c("ID", "LAB_DT"))

一般来说,如果没有排序,可以从-Inf滚动。就像您的代码一样,即使最小值存在平局,这也只会选择一行:

mDT = unique(DT[, .(ID, LAB_DT)])[, TEST_RESULT := -Inf]
DT[DT[mDT, on=names(mDT), roll=-Inf, which=TRUE]]

最后,如果你只有这三列,你可以在这里使用为速度优化的min函数(见?GForce):

DT[, .(TEST_RESULT = min(TEST_RESULT)), by=.(ID, LAB_DT)]

【讨论】:

    【解决方案2】:
    library(dplyr)
    DT %>% 
    group_by(ID,LAB_DT) %>% 
    slice(which.min(TEST_RESULT))
    

    【讨论】:

    • OP 明确要求data.table 解决方案;不知道基于dplyr 的解决方案在此处有何帮助。
    猜你喜欢
    • 2020-07-24
    • 2015-11-30
    • 2012-04-17
    • 1970-01-01
    • 2021-07-23
    • 2015-06-26
    • 1970-01-01
    • 2016-01-07
    • 1970-01-01
    相关资源
    最近更新 更多