首页 > 解决方案 > R - 基于 Data.table 快速二进制搜索的子集,第二个键中有多个值

问题描述

我在https://cran.r-project.org/web/packages/data.table/vignettes/datatable-keys-fast-subset.html#multiple-key-point遇到了这个小插曲。

我的数据如下所示:

ID    TYPE     MEASURE_1    MEASURE_2
1     A        3            3
1     B        4            4
1     C        5            5
1     Mean     4            4
2     A        10           1
2     B        20           2
2     C        30           3
2     Mean     20           2

当我这样做时......一切都按预期工作。

setkey(dt, ID, TYPE)
dt[.(unique(ID), "A")] # extract SD of all IDs with Type A
dt[.(unique(ID), "B")] # extract SD of all IDs with Type B
dt[.(unique(ID), "C")] # extract SD of all IDs with Type C

每当我尝试这样的事情时,我想将键控子集基于第二个键的多个值,我只得到键 1 中唯一值的所有组合的结果,而向量中只定义了第二个值的第一个c()值钥匙。因此,它只采用向量中定义的第一个值并忽略所有后续值。

# extract SD of all IDs with one of the 3 types A/B/C    
dt[.(unique(ID), c("A", "B", "C")] 

# previous output is equivalent to 
dt[.(unique(ID), "A")] # extract SD of all IDs with Type A

# I want/expect
dt[TYPE %in% c("A", "B", "C")]

我在这里错过了什么,或者这是我不能用键控子集做的事情?

澄清一下:由于我不能在键控子集中遗漏键 1,因此小插图要求包含第一个键unique(key1)

并且在键 1 中定义多个键也可以按预期工作。

dt[.(c(1, 2), "A")] == dt[ID %in% c(1,2) & TYPE == "A"] # TRUE

标签: rdata.table

解决方案


在 data.table 文档(参见help("data.table")https://rdatatable.gitlab.io/data.table/reference/data.table.html#arguments)中,提到了:

输入到 i 的字符、列表和 data.frame 在内部使用 as.data.table 转换为 data.table。

因此,适用于 R (或 in data.frame)中的经典回收规则。即,.(unique(ID), c("A", "B", "C"))等价于list(unique(ID), c("A", "B", "C")),变为:

as.data.table(list(unique(ID), c("A", "B", "C")))

并且由于最长列表元素的长度(长度为c("A", "B", "C"))不是较短列表元素(长度为 )的倍数,因此unique(ID)您将收到错误消息。如果您希望将每个值与 中unique(ID)的每个元素结合起来c("A", "B", "C"),则应CJ(unique(ID), c("A", "B", "C"))改为使用。

所以你应该做的是dt[CJ(unique(ID), c("A", "B", "C"))]

请注意,这dt[.(unique(ID), "A")]可以正常工作,因为您只为第二个键传递了一个元素,并且这会被回收以匹配unique(ID).


推荐阅读