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
我有 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
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