【发布时间】:2018-05-12 08:37:36
【问题描述】:
我有一个关于 data.table 的问题。 我喜欢它,但我认为我有时会误用 .SD,如果在 data.table 中使用它很有趣,我希望能得到一些澄清。
以下是我认为我在滥用 .SD 的两个示例:
第一个是discussed here(感谢亨利的评论)
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 操作与分组操作中的替代方法相比非常慢。 即使您想分组到整个 data.table,替代方案也会稍微快一些(尽管这里的时间差可能不值得失去语法的清晰性):
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 吗?
提前感谢您的帮助。
【问题讨论】:
-
第一个问题,Subset by group with data.table 的可能重复项:“OP 运行缓慢的主要原因不仅在于其中包含
.SD,而且在于它以特定方式使用它 -通过调用[.data.table,目前它的开销很大,因此在循环中运行它(当一个人执行by时)会累积非常大的惩罚”。另请参阅Optimize .SD query to keep the elegance but make it faster 和其中的链接。 -
感谢您的链接。
-
当你想对多列进行操作(就像你已经展示过的那样)或在某个操作之后返回少数(或所有列)时,你通常会想要使用
.SD987654335@ 或DT[, .SD[1L], by = x]。您也可以将它用于条件连接,例如DT[x > 2, .SD[DT, x, on = .(y)]]。除此之外,我真的没有理由使用它,您可能会使用实际的向量。 -
这个问题太笼统了,如果可以的话,我会投票关闭它;我在有用的时候使用
.SD,这很常见——这不是一个好的答案,但这主要是因为这不是一个好问题 -
What does .SD stand for in data.table in R 的可能重复项。特别是考虑到@MichaelChirico 最近非常彻底的answer。
标签: r dataframe data.table