R使用data.table进行多个条件连接

我有一个大型数据集和一个查找表.我需要为数据集中的每一行返回查找中满足条件的行的最小值.

鉴于我的数据集的大小,我不愿意通过交叉连接来共同破解一个iffy解决方案,因为这将创建数百万条记录.我希望有人可以建议一个(理想情况下)利用base r或data.table的解决方案,因为它们已经以高效的方式使用.

A<-seq(1e4,9e4,1e4)
B<-seq(0,1e4,1e3)

dt1<-data.table(expand.grid(A,B),ID=1:nrow(expand.grid(A,B)))
setnames(dt1, c("Var1","Var2"),c("A","B"))

lookup<-data.table(minA=c(1e4,1e4,2e4,2e4,5e4),
                 maxA=c(2e4,3e4,7e4,6e4,9e4),
                 minB=rep(2e3,5),
                 Val=seq(.1,.5,.1))

# Sample  Desired Value
     A     B    ID Val
99: 90000 10000 99 0.5

在SQL中,我会写一些东西

SELECT ID, A, B, min(Val) as Val
FROM dt1
LEFT JOIN lookup on dt1.A>=lookup.minA
                 and dt1.A<=lookup.maxA
                 and dt1.B>=lookup.minB
GROUP BY ID, A, B

这将从查找到dt1连接所有匹配的记录并返回最小的Val.

更新

到目前为止我的解决方案如下:

CJ.table<-function(X,Y) setkey(X[,c(k=1,.SD)],k)[Y[,c(k=1,.SD)],allow.cartesian=TRUE][,k:=NULL]

dt1.lookup<- CJ.table(dt1,lookup)[A>=minA & A<=maxA & B>=minB,
                                  list(Val=Val[which.min( Val)]),
                                  by=list(ID,A,B)]
dt1.lookup<-rbind.fill(dt1.lookup, dt1[!ID %in% dt1.lookup$ID])

这将检索所有记录,并允许在需要时从查找表中返回其他列.它还具有强制选择最小Val的优点.

最佳答案 我发现没有交叉连接的解决方案首先需要通过去除A和B完全超出范围的行来准备数据:

Prep = dt1[A >= min(lookup$minA) & A <= max(lookup$maxA) & B >= min(lookup$minB)]

然后,您创建一个数据表,其中满足与最低Val对应的每个条件:

Indices = Prep[,list(min(which(A >= lookup$minA)), 
                     min(which(A <= lookup$maxA)), 
                     min(which(B >= lookup$minB)), A, B),by=ID]

那么你必须在满足所有三个条件的最低点得到Val:

Indices[,list(Val=lookup$Val[max(V1,V2,V3)], A, B),by=ID]

看看这是否能满足您的需求:

   ID Val     A     B
 1: 19 0.1 10000  2000
 2: 20 0.1 20000  2000
 3: 21 0.2 30000  2000
 4: 22 0.3 40000  2000
 5: 23 0.3 50000  2000
 6: 24 0.3 60000  2000
 7: 25 0.3 70000  2000
 8: 26 0.5 80000  2000
 9: 27 0.5 90000  2000
10: 28 0.1 10000  3000
点赞