在我看来,执行a的row/col子集的最快方法data.table
是使用join和nomatch
option.
它是否正确?
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
Run Code Online (Sandbox Code Playgroud)
基于二进制搜索的快速连接也存在一个问题:我找不到在一个维度中选择所有项目的方法.
如果我想要随后说:
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
Run Code Online (Sandbox Code Playgroud)
无需将密钥重新设置为只有一个维度(因为我在一个循环中,我不想每次都休息密钥).
tuc*_*son 12
data.table
?使用基于二进制搜索的子集功能是最快的.请注意,子集需要该选项,nomatch = 0L
以便仅返回匹配的结果.
如果您设置了两个键,DT
并且您希望按第一个键进行子集,那么您可以只提供第一个值,而不需要为第二个键提供任何内容.那是:J(.)
# will return all columns where the first key column matches 22
DT[J(22), nomatch=0L]
Run Code Online (Sandbox Code Playgroud)
相反,如果您希望按第二个键进行子集,那么到目前为止,您必须为第一个键提供所有唯一值.那是:
# will return all columns where 2nd key column matches 2
DT[J(unique(V1), 2), nomatch=0L]
Run Code Online (Sandbox Code Playgroud)
这也在SO帖子中显示.虽然我更愿意DT[J(, 2)]
为这种情况工作,因为这似乎相当直观.
还有一个待处理的功能请求,FR#1007用于实现二级密钥,完成后将处理此问题.
这是一个更好的例子:
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
Run Code Online (Sandbox Code Playgroud)
综上所述:
# key(DT) = c("V1", "V2")
# data.frame | data.table equivalent
# =====================================================================
# subset(DF, (V1 == 3) & (V2 == 2)) | DT[J(3,2), nomatch=0L]
# subset(DF, (V1 == 3)) | DT[J(3), nomatch=0L]
# subset(DF, (V2 == 2)) | DT[J(unique(V1), 2), nomatch=0L]
Run Code Online (Sandbox Code Playgroud)