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

Does order of columns matter in data.table indexing (setkey)?

我对索引 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]

首先,您的 length(unique(B, na.rm = T)) 位并没有像您想象的那样工作 --na.rm = TRUE 不是 unique 的参数,它被传递给 ...并被忽略(感谢@ak运行 指出这一点)。从中得到你想要的东西的最好方法可能是 运行 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]
}

这是每个 ar运行gement 重复 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  

从这个简单的例子来看,您最好的选择是:不要键入 table(预排序的收益似乎很小),或者先键入 (A,B) 然后离开它。

反向——先按 (B,A) 键然后离开——也表现得很好。鉴于此,我真的很惊讶 XBA 的表现如此糟糕。


如果你想知道为什么它似乎没有键控那么快,它基本上是所有键控所做的,对于你想要做的,是预排序数据;这只会在给定操作中最低限度地提高速度,但必须在操作之间重新输入密钥是一种成本。按照手册的说法,这是 keyed byad hoc by:

相比

When by contains the first n columns of x's key, we call this a keyed by. In a keyed by the groups appear contiguously in RAM and memory is copied in bulk internally, for extra speed. Otherwise, we call it an ad hoc by. Ad hoc by is still many times faster than tapply, for example, but just not as fast as keyed by when datasets are very large, in particular when the size of each group is large. Not to be confused with keyby= defined below.

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