1) Использование входных данных, воспроизводимых в примечании в конце, и допущение, что компоненты Num
находятся в одинаковом порядке как в T1
, так и T2
(что имеет место с данными в вопросе - мы ослабим это предположение позже) мы можем использовать replace
для преобразования T1.Num
в шаблон like
и затем сопоставить его с T2.Num
, выполняющим левое соединение.
library(sqldf)
sqldf("select T1.*, T2.Item, T2.Num Num2 from T1
left join T2 on T2.Num like '%' || replace(T1.Num, ', ', '%') || '%'")
дает:
Name Age Num Item Num2
1 John 20 a, c, b pen a, c, q, b
2 Lily 19 d, h, e pencil d, z, h, e
3 Jake 10 a, d <NA> <NA>
Если это не тот случай, когда компоненты Num
упорядочены одинаково в T1
и T2
, то сначала сортируйте их следующим образом:
library(dplyr)
library(tidyr)
T1x <- T1 %>%
separate_rows(Num) %>%
arrange(Name, Num) %>%
group_by(Name) %>%
summarize(Num = toString(Num)) %>%
ungroup
T2x <- T2 %>%
separate_rows(Num) %>%
arrange(Item, Num) %>%
group_by(Item) %>%
summarize(Num = toString(Num)) %>%
ungroup
sqldf("select T1x.*, T2x.Item, T2x.Num Num2 from T1x
left join T2x on T2x.Num like '%' || replace(T1x.Num, ', ', '%') || '%'")
2) Эта альтернатива использует dplyr и tidyr без sqldf.
T1Long <- T1 %>%
separate_rows(Num)
T1Long %>%
left_join(T1Long %>% count(Name), by = "Name") %>%
left_join(T2 %>% separate_rows(Num), by = "Num") %>%
group_by(Name, Item, n) %>%
summarize(Num = toString(Num), Count = n()) %>%
ungroup %>%
filter(Count == n) %>%
select(-Count, -n)
дает:
# A tibble: 2 x 3
Name Item Num
<chr> <chr> <chr>
1 John pen a, c, b
2 Lily pencil d, h, e
Примечание
Вход в воспроизводимой форме:
Lines1 <- "
Name Age Num
John 20 a, c, b
Lily 19 d, h, e
Jake 10 a, d"
Lines2 <- "
Item Num
pen a, c, q, b
pencil d, z, h, e
apple a, c, y"
T1 <- read.table(text = gsub(" +", ";", trimws(readLines(textConnection(Lines1)))),
header = TRUE, sep = ";", as.is = TRUE)
T2 <- read.table(text = gsub(" +", ";", trimws(readLines(textConnection(Lines2)))),
header = TRUE, sep = ";", as.is = TRUE)