在我看来,执行data.table
的row / col子集的最快方法是使用join和nomatch
选项。
这是对的吗?
DT = data.table(rep(1:100, 100000), rep(1:10, 1000000))
setkey(DT, V1, V2)
system.time(DT[J(22,2), nomatch=0L])
# user system elapsed
# 0.00 0.00 0.01
system.time(subset(DT, (V1==22) & (V2==2)))
# user system elapsed
# 0.45 0.21 0.67
identical(DT[J(22,2), nomatch=0L],subset(DT, (V1==22) & (V2==2)))
# [1] TRUE
基于二进制搜索的快速连接也存在一个问题:我无法找到一种方法来选择一维中的所有项目。
说我是否愿意随后做:
DT[J(22,2), nomatch=0] # subset on TWO dimensions
DT[J(22,), nomatch=0] # subset on ONE dimension only
# Error in list(22, ) : argument 2 is empty
无需将密钥重新设置为仅一个维度(因为我处于循环中,而且我不想每次都按键休息)。
答案 0 :(得分:12)
data.table
使用基于二进制搜索的子集功能是最快的。请注意,子集需要选项nomatch = 0L
,以便仅返回匹配的结果。
如果您在DT
上设置了两个密钥,而您想通过第一个密钥 子集,那么您只需提供{中的第一个值} {1}},无需为第二个密钥提供任何内容。那就是:
J(.)
相反,如果您希望按第二个键进行分组,那么到目前为止,您必须提供第一个键的所有唯一值。那就是:
# will return all columns where the first key column matches 22
DT[J(22), nomatch=0L]
这也显示为in this SO post。虽然我更希望# will return all columns where 2nd key column matches 2
DT[J(unique(V1), 2), nomatch=0L]
适用于这种情况,因为这似乎相当直观。
还有一个待处理的功能请求,FR #1007用于实现辅助密钥,完成后会处理这个问题。
这是一个更好的例子:
DT[J(, 2)]
总结:
DT = data.table(c(1,2,3,4,5), c(2,3,2,3,2))
DT
# V1 V2
# 1: 1 2
# 2: 2 3
# 3: 3 2
# 4: 4 3
# 5: 5 2
setkey(DT,V1,V2)
DT[J(unique(V1),2)]
# V1 V2
# 1: 1 2
# 2: 2 2
# 3: 3 2
# 4: 4 2
# 5: 5 2
DT[J(unique(V1),2), nomatch=0L]
# V1 V2
# 1: 1 2
# 2: 3 2
# 3: 5 2
DT[J(3), nomatch=0L]
# V1 V2
# 1: 3 2