【问题标题】:Subsetting data.table by not head(key(DT),m), using binary search not vector scan通过 not head(key(DT),m) 对 data.table 进行子集,使用二进制搜索而不是矢量扫描
【发布时间】:2013-04-02 16:54:22
【问题描述】:

如果我将 n 列指定为 data.table 的键,我知道只要我加入 key(DT)head,我就可以加入比该键中定义的更少的列。例如,对于 n=2 :

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

那里我只加入了DT 的两列键的第一列。我知道我可以像这样加入键的两列:

X[J(3,1)]
   A B
1: 3 1

但是我如何只使用键的第二列(例如B==2)进行子集化,但仍然使用二进制搜索而不是矢量扫描?我知道这是重复的:

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

所以我想将这个问题概括为n。我的数据集有大约一百万行,上面链接的 dup 问题中提供的解决方案似乎不是最佳的。

【问题讨论】:

  • @MatthewPlourde,你确定吗?您引用的小插图有以下句子,使您的解决方案听起来不太理想:“我们使用密钥来利用表已排序的事实,并使用二进制搜索来查找匹配的行。我们没有矢量扫描;我们没有使用 ==。”
  • 我可能已经把它标记为重复了...
  • @GSee 对我来说似乎是一个骗局。对 dup 的公认答案很好,但我们希望做得更好;例如当set2key 实现时。
  • @MatthewDowle 该解决方案没有为 OP 的数据提供正确的结果。

标签: r data.table


【解决方案1】:

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

 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); .. means "look up one level"
  ud <-  lapply([, ..whichUnique], 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

我不确定这会比在大型 data.table 上进行几次矢量扫描更快。

【讨论】:

    【解决方案2】:

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

    FR#1007 Build in secondary keys

    与此同时,我们陷入了向量扫描,或者问题中链接的 n=2 案例的答案中使用的方法(@mnel 在他的回答中很好地概括了这一点)。

    【讨论】:

      猜你喜欢
      • 2013-03-13
      • 2014-01-10
      • 1970-01-01
      • 1970-01-01
      • 2021-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多