Проверьте, все ли строки одной таблицы содержатся в другой таблице - PullRequest
0 голосов
/ 06 января 2019

У меня есть две таблицы T1 (3 столбца) и T2 (2 столбца)

T1:

Name  Age  Num
John  20   a, c, b
Lily  19   d, h, e

Т2:

Item    Num
pen     a, c, q, b
pencil  d, z, h, e
apple   a, c, y

Код столбца в строковом формате. Я хочу проверить, есть ли в T1 $ Num все числа в T2 $ Num, и добавить соответствующий элемент T2 $ в T1. Код что-то вроде

 T1 <- sqldf("SELECT *, T2.Item FROM T1 LEFT JOIN T2 WHERE T1.Num are all contained in T2.Num")

Я должен получить

Name  Age  Num         Item
John  20   a, c, b     pen
Lily  19   d, h, e     pencil

Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 07 января 2019

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...