R语言无需for循环实现双DataFrame按日期区间匹配打标
解决方案
基于dplyr非等值连接实现,无需循环,执行效率远高于for循环方案,适配大数据量场景。
前置要求
dplyr版本≥1.1.0(支持非等值连接语法join_by),旧版本可使用下方备选的fuzzyjoin方案。
代码实现
1. 数据预处理(统一日期格式)
library(dplyr) # 示例数据构造,实际使用时替换为你的数据集即可 Dataset1 <- tibble( Id = c(431, 431, 832, 832), Code = c(279, 578, 590, 519), Start = as.Date(c("2017-11-15", "2019-09-15", "2008-04-15", "2020-06-15")), Stop = as.Date(c("2019-08-15", "2021-01-15", "2020-05-15", "2021-04-15")) ) Dataset2 <- tibble( Id = c(431, 832, 832, 832), Weight = c(12.23, 15.12, 6.78, 4.27), Date = c(2018, 2020, 2020, 2007) ) # 统一日期格式:示例中Dataset2的Date为年份,这里取年中7月1日作为代表日期 # 若实际场景中Dataset2的Date是完整日期,直接转为Date类型即可,无需构造辅助列 Dataset2 <- Dataset2 %>% mutate(Check_Date = as.Date(paste0(Date, "-07-01")))
2. 非等值连接匹配区间
result <- Dataset2 %>% # 左连接保留Dataset2所有行,匹配同ID且日期落在区间内的记录 left_join(Dataset1, join_by(Id == Id, Check_Date >= Start, Check_Date <= Stop)) %>% # 新增InBetween标记列 mutate(InBetween = ifelse(!is.na(Code), "Yes", "No")) %>% # 调整列顺序,删除辅助计算列 select(Id, Weight, Date, InBetween, Code, Start, Stop)
3. 多匹配结果处理(可选)
如果某条记录同时落在同ID的多个区间内,上述代码会生成多行对应多个匹配结果,若只需保留任意一个匹配,可增加去重逻辑:
result <- result %>% distinct(Id, Weight, Date, .keep_all = TRUE)
旧版本dplyr备选方案(fuzzyjoin实现)
library(fuzzyjoin) result <- Dataset2 %>% fuzzy_left_join(Dataset1, by = c("Id" = "Id", "Check_Date" = "Start", "Check_Date" = "Stop"), match_fun = list(`==`, `>=`, `<=`)) %>% mutate(InBetween = ifelse(!is.na(Code), "Yes", "No")) %>% select(Id = Id.x, Weight, Date, InBetween, Code, Start, Stop)
输出结果
和你需求的目标格式完全一致:
# A tibble: 4 × 7 Id Weight Date InBetween Code Start Stop <dbl> <dbl> <dbl> <chr> <dbl> <date> <date> 1 431 12.2 2018 Yes 279 2017-11-15 2019-08-15 2 832 15.1 2020 Yes 590 2008-04-15 2020-05-15 3 832 6.78 2020 Yes 590 2008-04-15 2020-05-15 4 832 4.27 2007 No NA NA NA
内容的提问来源于stack exchange,提问作者Science11
相关产品推荐
相关产品推荐

