R语言基于n_pz与日期范围实现内连接、左连接合并数据集
错误原因分析
- 基础包merge方法问题:第一次合并后未匹配到检查记录的行buffer_date为NA,日期逻辑判断返回NA会被subset直接过滤,导致中间结果s仅保留匹配成功的行,后续二次merge属于多余操作,也无法实现保留所有db_1记录的需求。
- dplyr方法问题:
left_join的by参数仅支持等值连接的字段匹配,不能直接写入不等值判断逻辑,你输入的逻辑表达式直接返回了布尔值FALSE,因此会提示找不到FALSE字段。
正确实现方案
1. 不等值连接(左连接+内连接)
dplyr版本(推荐,1.1.0及以上版本支持join_by语法)
library(dplyr) fmt <- "%d/%m/%Y" # 统一转换日期格式 db_11 <- transform(db_1, admission_date = as.Date(admission_date, fmt), discharge_date = as.Date(discharge_date, fmt)) db_21 <- transform(db_2, buffer_date = as.Date(buffer_date, fmt)) # 左连接:保留所有db_1的住院患者,仅匹配住院期间的检查记录 left_result <- left_join( db_11, db_21, join_by(n_pz, buffer_date >= admission_date, buffer_date <= discharge_date) ) # 内连接:仅保留住院期间有对应检查记录的患者 inner_result <- inner_join( db_11, db_21, join_by(n_pz, buffer_date >= admission_date, buffer_date <= discharge_date) )
如果使用旧版dplyr无join_by功能,可采用先等值连接再过滤的方式:
# 旧版dplyr左连接实现 left_result <- left_join(db_11, db_21, by = "n_pz") %>% filter((buffer_date >= admission_date & buffer_date <= discharge_date) | is.na(buffer_date)) # 旧版dplyr内连接实现 inner_result <- inner_join(db_11, db_21, by = "n_pz") %>% filter(buffer_date >= admission_date & buffer_date <= discharge_date)
基础包版本
fmt <- "%d/%m/%Y" db_11 <- transform(db_1, admission_date = as.Date(admission_date, fmt), discharge_date = as.Date(discharge_date, fmt)) db_21 <- transform(db_2, buffer_date = as.Date(buffer_date, fmt)) # 左连接实现 merge_raw_left <- merge(db_11, db_21, by = "n_pz", all.x = TRUE) left_result <- merge_raw_left[with(merge_raw_left, (buffer_date >= admission_date & buffer_date <= discharge_date) | is.na(buffer_date)), ] # 内连接实现 merge_raw_inner <- merge(db_11, db_21, by = "n_pz") inner_result <- merge_raw_inner[with(merge_raw_inner, buffer_date >= admission_date & buffer_date <= discharge_date), ]
2. 多检查记录转宽表
使用tidyr的pivot_wider实现,同一患者的多条检查会按顺序生成buffer_date_1、buffer_result_1、buffer_date_2、buffer_result_2这类列,无检查记录的患者对应检查字段为NA:
library(tidyr) wide_result <- left_result %>% # 按患者分组为每条检查生成序号 group_by(n_pz) %>% mutate(check_seq = row_number()) %>% ungroup() %>% # 转宽表 pivot_wider( id_cols = c(n_pz, admission_date, discharge_date), names_from = check_seq, values_from = c(buffer_date, buffer_result), names_sort = TRUE )
内容的提问来源于stack exchange,提问作者ArTu
相关产品推荐
相关产品推荐

