如何基于最近深度ID无间隙合并两个不等长数据集?
基于最接近深度ID的无冗余全连接实现
需求说明:对两个长度不等的数据集df_a与df_b,基于深度值作为ID执行全连接,要求每个df_b条目仅匹配df_a中深度值最接近的唯一条目,且不产生重复匹配,最终保留df_a的所有行,匹配成功的填充df_b对应数据,未匹配的填充NA。
示例数据
library(tibble) # 数据集df_a Depth_a <- seq(1, 10) value_a <- c(10, 12, 8, 5, 20, 33, 0, 3, 5, 14) df_a <- tibble(Depth_a, value_a) # 数据集df_b Depth_b <- c(1.2, 3.2, 7.2, 10.2) value_b <- c(4, 8, 14, 17) df_b <- tibble(Depth_b, value_b)
现有方法的问题
尝试使用dplyr的full_join结合join_by(closest(Depth_a <= Depth_b)),会出现重复匹配:
# 错误实现的结果 df_a %>% full_join(df_b, join_by(closest(Depth_a <= Depth_b)))
实际结果中,单个df_b条目会匹配多个df_a行(如Depth_b=10.2匹配了Depth_a=8/9/10),不符合"唯一匹配"的要求。
预期结果
最终合并后的数据应只保留df_a的所有行,每个df_b条目仅对应一个最接近的df_a深度:
# 预期输出结构 # A tibble: 10 × 3 Depth value_a value_b <int> <dbl> <dbl> 1 1 10 4 2 2 12 NA 3 3 8 8 4 4 5 NA 5 5 20 NA 6 6 33 NA 7 7 0 14 8 8 3 NA 9 9 5 NA 10 10 14 17
更直接的实现方案
核心思路:先为每个df_b条目找到唯一的最接近Depth_a,再与df_a执行左连接,避免重复匹配。
方法1:利用距离矩阵匹配
library(dplyr) # 计算所有Depth_b与Depth_a的绝对距离矩阵 dist_matrix <- outer(df_b$Depth_b, df_a$Depth_a, FUN = abs) # 为每个Depth_b找到距离最小的Depth_a索引 match_indices <- apply(dist_matrix, 1, which.min) # 给df_b绑定匹配的Depth_a df_b_matched <- df_b %>% mutate(Depth_a = df_a$Depth_a[match_indices]) # 左连接得到最终结果 final_result <- df_a %>% left_join(df_b_matched, by = "Depth_a") %>% rename(Depth = Depth_a) %>% select(Depth, value_a, value_b)
方法2:用purrr实现逐行匹配
library(dplyr) library(purrr) df_b_matched <- df_b %>% mutate(Depth_a = map_dbl(Depth_b, ~ which.min(abs(df_a$Depth_a - .x)))) final_result <- df_a %>% left_join(df_b_matched, by = "Depth_a") %>% rename(Depth = Depth_a) %>% select(Depth, value_a, value_b)
这两种方法都先完成df_b到df_a的唯一匹配映射,再合并数据集,全程无中间冗余步骤,直接得到符合要求的结果。
内容的提问来源于stack exchange,提问作者Antoine Lachance
相关产品推荐
相关产品推荐

