我有一个关于data.table的问题。
我喜欢它,但我认为我有时会误用 .SD,我希望能够澄清何时在data.table中使用它是有意义的。以下是两个例子,让我认识到我可能误用了.SD:
第一个例子是在这里讨论的(感谢Henry的评论)。
所以我的问题是:是否还有其他需要/有趣使用.SD的情况?
非常感谢您的帮助。
library(microbenchmark)
library(data.table)
DTlength <- 2000
DT <-
data.table(
id = rep(sapply(combn(LETTERS, 6, simplify = FALSE), function(x) {
paste(x, collapse = "")
}), each = 4)[1:DTlength],
replicate(10, sample(1001, DTlength, replace = TRUE)),
Answer = sample(c("Yes", "No"), DTlength, TRUE)
)
microbenchmark(
"without SD" = {
b <- DT[, Answer[1], by = id][, V1]
},
"without SD alternative" = {
b <- DT[DT[, .I[1], by = id][, V1], Answer]
},
"with SD" = {
b <- DT[, .SD[1, Answer], by = id][, V1]
}
)
Unit: microseconds
expr min lq mean median uq max neval
without SD 455.795 493.949 569.4979 529.847 558.564 2323.283 100
without Sd alternative 961.231 1010.667 1160.9114 1060.513 1113.641 7783.798 100
with SD 121217.691 123557.590 131071.5699 127495.437 130340.977 240317.227 100
与分组操作中的替代方法相比,.SD 操作速度较慢。 即使您想对整个数据表进行分组,使用其他方法稍微快一些(尽管在这里的时间差异可能不值得以语法清晰为代价):
microbenchmark(
"with SD" = {b <-DT[,.SD[1], by = id]},
"Without SD" = {b <- DT[DT[,.I[1],by = id][,V1]]}
)
Unit: milliseconds
expr min lq mean median uq max neval
with SD 1.058872 1.361436 1.560866 1.643078 1.741540 1.960206 100
Without SD 1.067898 1.169642 1.279443 1.233437 1.348719 1.781334 100
第二个示例说明了在组内使用条件将新变量赋值给一个值时,你不能真正使用 .SD(或者我没有找到方法):
DT[, .SD[V1 - V1[1] > 100][, plouf2 := Answer], by = id] # doesn't assign plouf2
DT[DT[, .I[V1 - V1[1] > 100], by = id][, V1], plouf2 := Answer] # this does
我发现使用.SD有两种情况非常有用:一种是在DT[,lapply(.SD,fun),.SDcols = ]
中使用,非常方便;另一种是当我们想要将组内所有值分配给满足特定条件的特定值时:
DT[, plouf3 := .SD[V1 - V1[1] > 100, Answer][1], by = id]
# all values are assigned, which is actually different from
DT[DT[, .I[V1 - V1[1] > 100][1], by = id][, V1], plouf2 := Answer]
# where only the values that match the condition V1-V1[1]>100 are assigned
所以我的问题是:是否还有其他需要/有趣使用.SD的情况?
非常感谢您的帮助。
.SD
,而且是它以一种特定的方式使用它 - 通过调用[.data.table
,目前它具有巨大的开销,所以在循环中运行它(当一个人进行by
时)会累积非常大的惩罚。" 另请参见Optimize .SD query to keep the elegance but make it faster及其中的链接。 - Henrik.SD
,例如DT[, if(any(x > 2)) .SD, by = y]
或DT[, .SD[1L], by = x]
。您还可以将其用于条件连接,例如DT[x > 2, .SD[DT, x, on = .(y)]]
。除此之外,我真的看不出有什么理由使用它,您可能会使用实际向量。 - David Arenburg.SD
有用时,我会使用它,而这种情况相当普遍——这不是一个好答案,但主要是因为这不是一个好问题。 - eddi