我有关于索引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]
答案 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非常令人满意。