【发布时间】:2014-03-02 03:23:03
【问题描述】:
我有一个大型数据集和一个查找表。我需要为数据集中的每一行返回满足条件的查找行中存在的最小值。
鉴于我的数据集的大小,我不愿意通过交叉连接来破解一个不确定的解决方案,因为这会创建数百万条记录。我希望有人可以提出一个(理想情况下)利用 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
这将连接从lookup 到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 的好处。
【问题讨论】:
-
注意:使用
CJ(在data.table包中实现)会比expand.grid快。 -
@Arun 这是个好建议!非常感谢
-
查看我的编辑以对您现有的解决方案进行微调。
-
根据 A 和 B 的范围,您可能会考虑在交叉加入之前操纵
dt1,就像在这个问题中一样 stackoverflow.com/questions/16423817/… -
我的最后一次编辑可能是一个延伸,但你当然可以像 Senor O 那样预先过滤
dt1即。dt1.prep<-dt1[A>=lookup[,min(minA)] & A<=lookup[,max(maxA)] & B>=lookup[,min(minB)]]然后只交叉连接dt1.prep而不是整个dt1
标签: r data.table