У меня есть большой набор данных и таблица поиска. Мне нужно вернуть для каждой строки в наборе данных наименьшее значение, присутствующее для строк в поиске, где выполняются условия.R Множественное условие join using data.table
Учитывая размер моего набора данных, я неохотно взламываю решение iffy вместе, перекрестно соединяясь, так как это создаст много миллионов записей. Я надеюсь, что кто-то может предложить решение, которое (в идеале) использует базу 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
.
Update
Мое решение до сих пор выглядит следующим образом:
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
@ Арун - отличный совет! Большое спасибо –
см. Мое редактирование для незначительной настройки вашего существующего решения. –