使用二进制搜索而不是矢量扫描,通过非头(键(DT),m)子集数据

时间:2013-04-02 16:54:22

标签: r data.table

如果我指定n列作为data.table的键,我知道只要加入head {{}},我就可以加入少于该键中定义的列数。 {1}}。例如,对于n = 2:

key(DT)

我只加入了X = data.table(A=rep(1:5, each=2), B=rep(1:2, each=5), key=c('A','B')) X A B 1: 1 1 2: 1 1 3: 2 1 4: 2 1 5: 3 1 6: 3 2 7: 4 2 8: 4 2 9: 5 2 10: 5 2 X[J(3)] A B 1: 3 1 2: 3 2 的2列密钥的第一列。我知道我可以像这样加入密钥的两个列:

DT

但是,我如何仅使用密钥的第二列列(例如X[J(3,1)] A B 1: 3 1 )进行子集,但仍然使用二进制搜索而不是向量扫描?我知道这是重复的:

Subsetting data.table by 2nd column only of a 2 column key, using binary search not vector scan

所以我想将这个问题概括为B==2。我的数据集大约有一百万行,上面链接的双重问题提供的解决方案似乎并不是最优的。

2 个答案:

答案 0 :(得分:5)

这是一个简单的函数,它将提取正确的唯一值并返回一个数据表以用作键。

 X <- data.table(A=rep(1:5, each=4), B=rep(1:4, each=5), 
                  C = letters[1:20], key=c('A','B','C'))
 make.key <- function(ddd, what){
  # the names of the key columns
  zzz <- key(ddd)
  # the key columns you wish to keep all unique values
  whichUnique <- setdiff(zzz, names(what))
  ## unique data.table (when keyed)
  ud <-  lapply([,whichUnique, with = FALSE], unique)
  ## append the `what` columns and  a Cross Join of the new
  ## key columns
  do.call(CJ, c(ud,what)[zzz])
}   

X[make.key(X, what = list(C = c('a','b'))),nomatch=0]
## A B C
## 1: 1 1 a
## 2: 1 1 b

我不确定这会比大数据上的几个矢量扫描更快。但是。

答案 1 :(得分:1)

在功能请求列表中添加辅助密钥:

FR#1007 Build in secondary keys

与此同时,我们仍然坚持使用矢量扫描,或者在问题中链接的n = 2案例的答案中使用的方法(@mnel在答案中很好地概括了)。