R:合并部分匹配的数据

R: Merging data with partial matches

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

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

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

'|' 上使用 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.

使用 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

我们可以使用 fuzzyjoin

中的 regex_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