我们可以为此使用非 equi 连接。会更快更高效
library(data.table)
setDT(dat)[, newcol := dat_frame][df, on = .(dat_id = id,
newcol >= first, newcol <=last)][, .(dat_id, dat_frame, dat_data)]
# dat_id dat_frame dat_data
# 1: 27 14 26
# 2: 27 15 56
# 3: 27 16 30
# 4: 27 17 49
# 5: 27 20 23
# 6: 27 21 37
# 7: 27 22 7
# 8: 27 23 40
# 9: 27 24 12
#10: 134 9 57
#11: 134 10 35
#12: 134 11 31
#13: 134 12 53
#14: 134 13 38
#15: 134 16 15
#16: 134 17 14
#17: 134 18 33
#18: 134 19 54
#19: 134 20 43
或者另一个选项是fuzzyjoin
library(fuzzyjoin)
library(dplyr)
dat %>%
mutate(newcol = dat_frame) %>%
fuzzy_left_join(df, by = c("dat_id" = 'id', 'newcol' = 'first',
'newcol' = 'last'), match_fun = list(`==`, `>=`, `<=`)) %>%
na.omit %>%
select(dat_id, dat_frame, dat_data)
# dat_id dat_frame dat_data
#14 27 14 26
#15 27 15 56
#16 27 16 30
#17 27 17 49
#20 27 20 23
#21 27 21 37
#22 27 22 7
#23 27 23 40
#24 27 24 12
#39 134 9 57
#40 134 10 35
#41 134 11 31
#42 134 12 53
#43 134 13 38
#46 134 16 15
#47 134 17 14
#48 134 18 33
#49 134 19 54
#50 134 20 43
或者使用base R
out <- do.call(rbind, Map(function(x, y) do.call(rbind,
Map(function(u, v) subset(x, dat_frame >= u & dat_frame <= v),
y$first, y$last)), split(dat, dat$dat_id), split(df, df$id)))
row.names(out) <- NULL
out
# dat_id dat_frame dat_data
#1 27 14 26
#2 27 15 56
#3 27 16 30
#4 27 17 49
#5 27 20 23
#6 27 21 37
#7 27 22 7
#8 27 23 40
#9 27 24 12
#10 134 9 57
#11 134 10 35
#12 134 11 31
#13 134 12 53
#14 134 13 38
#15 134 16 15
#16 134 17 14
#17 134 18 33
#18 134 19 54
#19 134 20 43
注意:以上所有解决方案都有效
另外,请注意,另一篇文章中的解决方案给出了Error
left_join(dat, df, by = c("dat_id" = "id")) %>%
filter(between(dat_frame, first, last)) %>%
select(-first, -last)
#Error: Expecting a single value: [extent=120].
注意:接受的答案是错误的并且它给出了错误。