R语言连接两同变量数据框时直接合并非空值的简化方案
R 按列全连接两表时自动合并非空值的实现
问题场景
我需要匹配Data_Frame_2中的非空值,示例如下:
Data_Frame #> Training Pulse Duration #> 1 Strength 100 60 #> 2 Stamina 150 30 #> 3 Other NA 45 Data_Frame_2 #> Training Pulse Duration #> 1 Strength NA 90 #> 2 Other 30 NA #> 3 Dimension 2 1 # 常规全连接写法会输出带.x/.y后缀的列 Data_Frame %>% full_join(Data_Frame_2, by= c("Training"="Training")) #> Training Pulse.x Duration.x Pulse.y Duration.y #> 1 Strength 100 60 NA 90 #> 2 Stamina 150 30 NA NA #> 3 Other NA 45 30 NA #> 4 Dimension NA NA 2 1 # 现有逐列处理写法 Data_Frame %>% full_join(Data_Frame_2, by= c("Training"="Training")) %>% mutate(Pulse = if_else(is.na(Pulse.x), Pulse.y, Pulse.x), Duration = if_else(is.na(Duration.x), Duration.y, Duration.x)) %>% select(Training, Pulse, Duration) #> Training Pulse Duration #> 1 Strength 100 60 #> 2 Stamina 150 30 #> 3 Other 30 45 #> 4 Dimension 2 1
当前使用full_join按Training列全连接两个数据框后,需要逐列通过mutate配合if_else判断,优先保留第一个数据框的非空值,若为空则取第二个数据框的对应值,再通过select筛选目标列才能得到预期结果。希望省略连接后的逐列处理步骤,仅通过连接操作直接得到最终结果;由于待处理的两个数据框包含大量同名变量,逐列编写mutate逻辑会造成代码过度冗余,因此寻求更简洁的实现方案。
解决方案
不需要逐列手动编写判断逻辑,以下两种方案都可以自动处理所有同名列,无冗余代码:
- 方案1:兼容所有dplyr版本,自动批量合并同名列
library(dplyr) # 自动提取除连接键外的所有同名列,无需手动枚举 common_cols <- setdiff(intersect(names(Data_Frame), names(Data_Frame_2)), "Training") Data_Frame %>% full_join(Data_Frame_2, by = "Training", suffix = c("", ".y")) %>% mutate(across( .cols = all_of(common_cols), .fns = ~ coalesce(.x, get(paste0(cur_column(), ".y"))) )) %>% select(Training, all_of(common_cols))
- 方案2:dplyr 1.1.0及以上版本一步到位,连接时直接处理列冲突
library(dplyr) Data_Frame %>% full_join( Data_Frame_2, by = "Training", # 同名列冲突时,优先取左表非空值,空值自动补右表值 conflict = ~ coalesce(.x, .y) )
两种方案运行结果和预期完全一致,不管有多少个同名列,都不需要逐列写判断逻辑。
内容的提问来源于stack exchange,提问作者Mick
相关产品推荐
相关产品推荐

