R 使用可选(或)而不是连词在两列上使用键进行二进制搜索

R 使用可选(或)而不是连词在两列上使用键进行二进制搜索,r,filter,binary,key,data.table,R,Filter,Binary,Key,Data.table,我试图找到一种方法,用两个键过滤DT,使用替换键而不是连词。dplyr中的解决方案如下所示: filter(DF, A == a | B == b) 我在data.table中尝试做同样的事情,在A和B上都设置了键,但到目前为止运气不好 我不想使用DT[A==A | B==B]form,因为向量搜索的性能较低 让我们以下面的数据为例: DF <- data.frame(A = c(1, NA, 1, 2), B = c(NA, 3, 3, 5)) DF # A B # 1 1

我试图找到一种方法,用两个键过滤DT,使用替换键而不是连词。dplyr中的解决方案如下所示:

filter(DF, A == a | B == b)
我在
data.table
中尝试做同样的事情,在
A
B
上都设置了键,但到目前为止运气不好

我不想使用
DT[A==A | B==B]
form,因为向量搜索的性能较低

让我们以下面的数据为例:

DF <- data.frame(A = c(1, NA, 1, 2), B = c(NA, 3, 3, 5))
DF
#    A  B
# 1  1 NA
# 2 NA  3
# 3  1  3
# 4  2  5
filter(DF, A == 1 | B == 3)
#    A  B
# 1  1 NA
# 2 NA  3
# 3  1  3
DT <- as.data.table(DF)
setkey(DT, "A", "B")

DF感谢@Frank的回答——结果证明这是正确的方法。
弗兰克提出了
mya=DT[A==A,后者=TRUE];myb=DT[B==B,其中=TRUE];DT[union(mya,myb)]
,因为它执行两个二进制搜索

我在更大的数据集(97671 x 13)上做了一些基准测试,结果是这样的(还添加了一些有问题的尝试;添加了连接示例以进行比较):

>microbenchmark(过滤器(ref.transactions,TalentID==talent.id | RecurringProfileID==recurtive.profile.id),ref.transactions[TalentID==talent.id | RecurringProfileID==recurtive.profile.id],unique(rbindlist(ref.transactions[(talent.id)],ref.transactions[(unique(c(talent.id,NA)),recurtive.profile.id)]),unique(rbind)(ref.transactions[(talent.id)],ref.transactions[(unique(c(talent.id,NA)),recurtive.profile.id)],ref.transactions[(talent.id,recurtive.profile.id)],{mya=ref.transactions[TalentID==talent.id,which=TRUE];ref.transactions[union(mya,myb)])
单位:毫秒
expr最小lq平均uq最大neval
过滤器(参考事务,TalentID==talent.id | RecurringProfileID==Recurrent.profile.id)10.039814 11.874223 14.278728 12.560975 13.562596 45.023206 100
ref.transactions[TalentID==talent.id | RecurringProfileID==recurtive.profile.id]6.934124 7.838649 9.323780 8.2271868.822951 40.115687 100
唯一的(rbindlist(列表(参考事务[(talent.id)],参考事务[(唯一的(c(talent.id,NA)),重复出现的.profile.id)])9.859269 10.826785 13.546877 11.663016 13.073455 47.173324 100
唯一(rbind(参考交易记录[(talent.id)],参考交易记录[(唯一(c(talent.id,NA)),重复出现的.profile.id)])9.910144 11.027810 14.633140 11.663457 12.920559 57.256676 100
参考交易记录[(talent.id,recurtive.profile.id)]1.196426 1.316740 1.513665 1.470091 1 1.574857 2.799963 100
{mya=ref.transactions[TalentID==talent.id,which=TRUE]myb=ref.transactions[RecurringProfileID==recurrence.profile.id,which=TRUE]ref.transactions[union(mya,myb)]1.710616 1.978395 3.085824 2.121029 2.370705 30.513052 100
>df.res mya=ref.transactions[TalentID==talent.id,哪个=TRUE];myb=ref.transactions[RecurringProfileID==Recurrentive.profile.id,哪个=TRUE];dt.res等同(df.res,dt.res)
[1] 真的

只要确保你看到了:添加a总是值得赞赏的。好吧,你可以做
mya=DT[a==a,which=TRUE];myb=DT[B==B,which=TRUE];DT[union(mya,myb)]
一些相近的东西会起作用——但是没有一个可重复的例子,我没有机会检查;-)@kmo,当有一个列被平等性测试时--
DT[a==a]
DT[A%in%as]
——包将为该列打开“自动索引”,并使用二进制搜索。只要有可能,这个“辅助键”将被再次使用,例如,如果您以后做了
DT[A==另一个\u A]
但复合等式测试尚未优化。仅供参考,您可以为microbenchmark的每个arg指定名称,它们将显示在表中,而不是完整的代码,
microbenchmark(a={..},b={…})
> microbenchmark(filter(ref.transactions, TalentID == talent.id | RecurringProfileID == recurring.profile.id), ref.transactions[TalentID == talent.id | RecurringProfileID == recurring.profile.id], unique(rbindlist(list(ref.transactions[.(talent.id)], ref.transactions[.(unique(c(talent.id, NA)), recurring.profile.id)]))), unique(rbind(ref.transactions[.(talent.id)], ref.transactions[.(unique(c(talent.id, NA)), recurring.profile.id)])), ref.transactions[.(talent.id, recurring.profile.id)], {mya = ref.transactions[TalentID==talent.id,which=TRUE]; myb = ref.transactions[RecurringProfileID==recurring.profile.id,which=TRUE]; ref.transactions[union(mya,myb)]})
Unit: milliseconds
                                                                                                                                                                                                    expr       min        lq      mean    median        uq       max neval
                                                                                                       filter(ref.transactions, TalentID == talent.id | RecurringProfileID ==      recurring.profile.id) 10.039814 11.874223 14.278728 12.560975 13.562596 45.023206   100
                                                                                                               ref.transactions[TalentID == talent.id | RecurringProfileID ==      recurring.profile.id]  6.934124  7.838649  9.323780  8.227186  8.822951 40.115687   100
                                                                       unique(rbindlist(list(ref.transactions[.(talent.id)], ref.transactions[.(unique(c(talent.id,      NA)), recurring.profile.id)])))  9.859269 10.826785 13.546877 11.663016 13.073455 47.173324   100
                                                                                 unique(rbind(ref.transactions[.(talent.id)], ref.transactions[.(unique(c(talent.id,      NA)), recurring.profile.id)]))  9.910144 11.027810 14.633140 11.663457 12.920559 57.256676   100
                                                                                                                                                    ref.transactions[.(talent.id, recurring.profile.id)]  1.196426  1.316740  1.513665  1.470091  1.574857  2.799963   100
 {     mya = ref.transactions[TalentID == talent.id, which = TRUE]     myb = ref.transactions[RecurringProfileID == recurring.profile.id,          which = TRUE]     ref.transactions[union(mya, myb)] }  1.710616  1.978395  3.085824  2.121029  2.370705 30.513052   100
> df.res <- filter(ref.transactions, TalentID == talent.id | RecurringProfileID ==      recurring.profile.id)
> mya = ref.transactions[TalentID==talent.id,which=TRUE]; myb = ref.transactions[RecurringProfileID==recurring.profile.id,which=TRUE]; dt.res <- ref.transactions[union(mya,myb)]
> identical(df.res, dt.res)
[1] TRUE