列的顺序在data.table索引(setkey)中是否重要?

时间:2015-07-05 12:14:18

标签: r data.table

我有关于索引data.table个对象的问题。

setkey(data, A, B)
data[, C:=length(unique(B, na.rm=T)), by=A]

我想知道我应该将索引的顺序更改为

setkey(data, B, A)

提高速度。或者它们是一样的吗?我应该如何索引

data[c>=3, D:=sum(A), by=B]

1 个答案:

答案 0 :(得分:2)

首先,您的length(unique(B, na.rm = T))位未执行您认为的操作 - na.rm = TRUE不是unique的参数,而是传递给...并忽略(感谢@akrun指出这一点)。获得你想要的东西的最好方法可能就是运行uniqueN(na.omit(B))

考虑到这一点,我运行了9(= 3x3)个基准测试,比较了您建议的代码的速度(略微增强版本),改变了键控的顺序:(B,A)(A,B)或什么都没有(X)。例如,下面提到的BAX函数是:

BAX <- function(){
  data <- data.table(A = sample(50, size = 1e6, T),
                     B = sample(c(1:150000, NA), size = 1e6, T))
  setkey(data, B, A)
  data[ , C := uniqueN(na.omit(B)), by = A]
  data[C >= 18500, D := sum(A), by = B]
}

以下是每种安排重复200次的结果:

> microbenchmark(times = 200L,
                 XX(), XAB(), XBA(), ABX(), ABAB(),
                 ABBA(), BAX(), BAAB(), BABA())
Unit: milliseconds
   expr       min        lq     mean    median       uq      max neval    cld
   XX()  70.05867  73.66665 105.2628  96.55443 116.5883 213.2926   200 a     
  XAB() 112.52981 121.91760 161.2687 157.66455 172.6626 370.4791   200     ef
  XBA() 112.56648 122.65417 165.9513 158.96873 174.6038 406.3392   200      f
  ABX()  79.59582  82.33355 110.8462 101.04939 125.0158 198.1082   200 a     
 ABAB()  83.81686  90.40803 123.1391 126.94853 132.0878 182.0694   200  b    
 ABBA() 112.50687 117.68602 151.8467 155.72603 161.2123 228.5776   200    de 
  BAX()  85.82144  93.87965 134.5259 130.40824 146.1559 263.9083   200  bc   
 BAAB() 100.48214 105.35192 150.9692 146.76173 156.0230 392.4626   200    de 
 BABA()  93.29706 104.70251 142.8426 138.12848 149.1106 279.4645   200   cd  

从这个简单的例子开始,你最好的选择是:不要键入表格(预先排序的收益似乎很少),或者先按(A,B)键,然后保留。

反向键 - (B,A)首先离开它 - 也表现得非常好。鉴于此,我真的很惊讶XBA表现得很糟糕。

如果你想知道为什么在没有键控的情况下似乎如此之快,那么基本上所有键控都会对你正在尝试做的事情进行预先排序。这仅在给定操作中最小化速度,但是必须重新键入中间操作是成本。用手册的说法,这是一个键入 ad hoc by 相比:

  

by包含x键的前n列时,我们将其称为键入。在键入中,组在RAM中连续显示,内存在内部批量复制,以提高速度。否则,我们称之为 ad hoc by 。例如,Ad hoc by仍然比tapply快许多倍,但是当数据集非常大时,特别是当每个组的大小很大时,其速度不如关键时快。不要与下面定义的keyby =混淆。

键控的真正速度优势在于子集化和合并 - 对于像你这样的操作,我发现 ad hoc bys非常令人满意。