Данный:
library(data.table)
dat1 <- setDT(data.frame(pat=c("A.C",".BC"),val=c(1,2)))
dat2 <- setDT(data.frame(q=c("ABC","AXC","XBC"),val2=c(10,11,12)))
Я хочу, чтобы результат был:
dat3 <- setDT(data.frame(pat=c("A.C","A.C",".BC",".BC"),val=c(1,1,2,2),q=c("ABC","AXC","ABC","XBC"),val2=c(10,11,10,12)))
dat3
pat val q val2
1: A.C 1 ABC 10
2: A.C 1 AXC 11
3: .BC 2 ABC 10
4: .BC 2 XBC 12
Другими словами, левое соединение dat1 с dat2 для каждого совпадения шаблона регулярного выражения pat со строкой запроса q
Мне было интересно, возможно ли это с помощью краткого выражения слияния data.table, т.е.
dat1[dat2, .(pat, val, q, val2), on= .(grepl(pat,q))] # this does not work
или любой другой data.table трюк для эффективности. На самом деле dat1 — это сотни строк, а dat2 может быть 10–100 тысяч строк.
Это звучит достаточно просто, но я не нашел поста, который полностью освещал бы эту тему.
Самое близкое, что мне удалось сделать, это следующее:
match_pat_to_q <- function(pattern, data, data.col = "q"){
ret<-lapply(pattern, function(x){
data[grepl(x,get(data.col))]
})
names(ret) <- pattern # becomes an .id column in next step
rbindlist(ret, idcol=TRUE)
}
match_pat_to_q(dat1$pat, dat2)[dat1, on=.(.id==pat)]
.id q val2 val
1: A.C ABC 10 1
2: A.C AXC 11 1
3: .BC ABC 10 2
4: .BC XBC 12 2





Вы можете решить свою проблему следующим образом:
dat1[, dat2[grep(pat, q), .(val, x=q, val2)], by=pat]
pat val x val2
<char> <num> <char> <num>
1: A.C 1 ABC 10
2: A.C 1 AXC 11
3: .BC 2 ABC 10
4: .BC 2 XBC 12
Вы группируете dat1 по pat. Это позволяет логически создать одну группу для каждого шаблона в dat1. Затем для каждой группы вы фильтруете соответствующие данные из dat2, используя сопоставление с образцом, одновременно выбирая необходимые переменные.