【问题标题】:R: Merging data with partial matchesR:合并部分匹配的数据
【发布时间】:2026-02-11 12:15:01
【问题描述】:

我有 2 个数据框,我试图根据全部/部分匹配将它们合并在一起。这 2 个数据帧有一列具有匹配的标识符 (ID2),但是其中一个数据帧中的某些行可以具有由“|”分隔的标识符组合符号。

两个数据帧结果的基本合并

df1 <- data.frame(
  ID1 = c("A1", "A2", "A3", "A4", "A5"),
  ID2 = c("B1|B2", "B1", "B3", "B6|B4", "B0|B6|B3")
)

df2 <- data.frame(
  ID3 = c("C1", "C2", "C3", "C4", "C5"),
  ID2 = c("B1", "B2", "B3", "B4", "B5")
)

merge(df1, df2, by = "ID2")
  ID2 ID1 ID3
1  B1  A2  C1
2  B3  A3  C3

这会导致一个数据帧中只找到了 2 个匹配项,但我还想为诸如“B0|B6|B3”之类的行找到匹配项,其中 B0 和 B6 不存在于第二个数据帧中,但是 B3仍然是 2 个数据帧之间的匹配项。

所需的输出如下所示:

  ID1      ID2   ID3
1  A1    B1|B2 C1|C2
2  A2       B1    C1
3  A3       B3    C3
4  A4    B6|B4    C4
5  A5 B0|B6|B3    C3

【问题讨论】:

    标签: r merge


    【解决方案1】:

    使用grepl + sapply + apply 的基本 R 选项

    transform(
      df1,
      ID3 = apply(
        sapply(
          df2$ID2,
          function(x) grepl(x, ID2)
        ),
        1,
        function(k) paste0(df2$ID3[k], collapse = "|")
      )
    )
    

    给予

      ID1      ID2   ID3
    1  A1    B1|B2 C1|C2
    2  A2       B1    C1
    3  A3       B3    C3
    4  A4    B6|B4    C4
    5  A5 B0|B6|B3    C3
    

    【讨论】:

      【解决方案2】:

      我们可以使用来自fuzzyjoinregex_left_join

      library(fuzzyjoin)
      library(dplyr)
      regex_left_join(df1, df2, by = "ID2") %>% 
         group_by(ID1, ID2 = ID2.x) %>% 
         summarise(ID3 = str_c(ID3, collapse="|"), .groups = 'drop')
      

      -输出

      # A tibble: 5 x 3
        ID1   ID2      ID3  
        <chr> <chr>    <chr>
      1 A1    B1|B2    C1|C2
      2 A2    B1       C1   
      3 A3    B3       C3   
      4 A4    B6|B4    C4   
      5 A5    B0|B6|B3 C3   
      

      【讨论】:

        【解决方案3】:

        使用separate_rows 拆分'|' 获取长格式数据,并为每个ID1 汇总一个串联字符串中的值。

        library(dplyr)
        library(tidyr)
        
        df1 %>%
          separate_rows(ID2, sep = '\\|') %>%
          left_join(df2, by = "ID2") %>%
          group_by(ID1) %>%
          summarise(across(c(ID2, ID3), ~paste0(na.omit(.), collapse = '|')))
        
        #  ID1   ID2      ID3  
        #  <chr> <chr>    <chr>
        #1 A1    B1|B2    C1|C2
        #2 A2    B1       C1   
        #3 A3    B3       C3   
        #4 A4    B6|B4    C4   
        #5 A5    B0|B6|B3 C3   
        

        如果对于每个 ID,可以保证在 df2 中至少有 1 个匹配项,如示例中所示,您可以使用 inner_join 并删除 na.omit

        【讨论】: