慢 data.table 子集与 dplyr

Ale*_*lex 4 r data.table

我一直在使用以下格式的dplyr代码

 group_by(dt, ID) %>%
    filter(any(colY == 1 & colX == 10))
Run Code Online (Sandbox Code Playgroud)

像下面这样对 data.table 进行子集化

ID colX colY
1111 3 1
1111 2 1
1111 6 0
1111 9 0
2222 10 1
2222 3 1
2222 5 0
2222 7 0
3333 8 1
3333 10 1
3333 3 0
3333 2 0

进入

ID colX colY
2222 10 1
2222 3 1
2222 5 0
2222 7 0
3333 8 1
3333 10 1
3333 3 0
3333 2 0

过滤大约 900k 行以获得第二个表大约需要 1.3 秒。

我一直在尝试实现一个更快的 data.table 子集,但到目前为止,结果只需要更长的时间。使用以下 data.table 子集

dt[ , .SD[any( (colY == 1 & colX == 10)) ], ID]
Run Code Online (Sandbox Code Playgroud)

大约需要 14 秒。这里似乎有什么问题?

Ric*_*ven 5

这可能会更快。它避免使用.SD并使用中给出的行号.I

dt[dt[, .I[any(colX == 10 & colY == 1)], by = ID]$V1]
#      ID colX colY
# 1: 2222   10    1
# 2: 2222    3    1
# 3: 2222    5    0
# 4: 2222    7    0
# 5: 3333    8    1
# 6: 3333   10    1
# 7: 3333    3    0
# 8: 3333    2    0
Run Code Online (Sandbox Code Playgroud)

内部数据表调用dt[, .I[any(colX == 10 & colY == 1)], by = ID]$V1为我们提供了符合我们条件的那些组的行号。 .I给我们每个组的行位置。我们可以通过打印我们的调用来查看结果:

dt[, print(.I[any(colX == 10 & colY == 1)]), by = ID]
# integer(0)
# [1] 5 6 7 8
# [1]  9 10 11 12
# Empty data.table (0 rows) of 1 col: ID
Run Code Online (Sandbox Code Playgroud)

然后我们只使用该结果作为原始数据表上的行子集。

  • 这最终比我尝试的 data.table 子集快 75 倍。.SD 正在拉动 90k 组,这大大减慢了进程 (4认同)