我有一个关于索引 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]
我有一个关于索引 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
函数的一个参数,而是被传递给...
并被忽略(感谢@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]
}
> 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
的表现感到非常惊讶。
键排序的真正速度优势在于子集和合并,对于像你这样的操作,我发现“临时”的已经完全可以满足需求了。当
by
包含x
的键的前n列时,我们称之为“键控的”。在“键控的”中,组在RAM中连续出现,并且内部批量复制内存,以获得额外的速度。否则,我们称之为“临时的”。临时的仍然比tapply等操作快很多倍,但是当数据集非常大时,特别是每个组的大小很大时,它不如键控的快。不要与下面定义的keyby
混淆。
length(unique(B))-any(is.na(B))
,如果我们使用 length(unique(na.omit(B)))
呢?在我看来,这可能需要一些严肃的计算。我非常感谢您详细的回答。谢谢! - JeanVudana.omit
确实是更好的选择。 - MichaelChirico
library(microbenchmark)
来测试它。在devel
版本中,你可以使用uniqueN
代替length(unique
。 - akrunmicrobenchmark
包自行测试。但据我所知,对于这种类型的操作,关键字并不重要;它用于使用i
参数进行快速选择。 - Nick Kennedymicorbenchmark
进行测试,但在一个简单的函数和小数据上得到了混合的结果。因此,我想问问作者或其他可能注意到差异的人。 - JeanVudaunique
函数也没有na.rm=TRUE
参数。unique(c('x', 'x', NA), na.rm=TRUE)
# [1] "x" NA - akrun