Сопоставление нескольких строк и присоединение - PullRequest
0 голосов
/ 31 января 2019

У меня проблемы с сопоставлением нескольких строк в r.Фрейм данных, который у меня есть, выглядит следующим образом:

      Var1                                      Var2
1   SJDJWK   P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4
2  ODJSMDK   Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4
3 JDKSAKDJ                       PE35RV747;P0F071G1G

Я бы хотел сопоставить строки, разделенные ";"со значениями в следующем фрейме данных:

      Var_x    Var_y
1 P04TGI7F3     good
2 P030Y7Y11   normal
3 PE35RV747      bad
4 Q2UKLVVX4   normal

Чтобы результирующий фрейм данных выглядел следующим образом:

      Var1                                      Var2                    Var3
1   SJDJWK   P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4  good;normal;bad;normal
2  ODJSMDK   Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4       normal;bad;normal
3 JDKSAKDJ                       PE35RV747;P0F071G1G                     bad

До сих пор я пытался сделать это с помощью нечеткого соединения:

fuzzy_left_join(Data1, Data2, by = c("Var2"="Var_x"), match_fun = str_detect)

Это делает работу, но использует много памяти (мой набор данных очень большой, и R перестает работать).Я пытался сделать это с помощью цикла for, но я не могу понять, как это сделать.Кто-то, кто знает?

Ответы [ 5 ]

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

В базе R вы можете построить именованный вектор из второго data.frame, затем после разделения мы ищем все соответствующие значения в этом именованном векторе, удаляем NA и вставляем обратно вместе.

df1$Var3 <- sapply(
  strsplit(df1$Var2,";"), 
  function(x) paste(na.omit(setNames(df2$Var_y,df2$Var_x)[x]), collapse=";"))

df1
#       Var1                                    Var2                   Var3
# 1   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
# 2  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4      normal;bad;normal
# 3 JDKSAKDJ                     PE35RV747;P0F071G1G                    bad
0 голосов
/ 31 января 2019

Другой вариант с gsubfn, где мы создаем list пар ключ / значение в replacement из gsubfn для pattern символов, которые не являются ;.Обратите внимание, что в некоторых случаях слова отсутствуют в «df2».Если есть все замены, то второй gsub не нужен (при условии, что в примере он не предоставлен)

library(gsubfn)
df1$Var_y <-  gsub(";[A-Z0-9]+", "", gsubfn("[^;]+",  
                setNames(as.list(df2$Var_y), df2$Var_x), df1$Var2))
df1
#      Var1                                    Var2                  Var_y
#1   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
#2  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4      normal;bad;normal
#3 JDKSAKDJ                     PE35RV747;P0F071G1G                    bad

data

df1 <- structure(list(Var1 = c("SJDJWK", "ODJSMDK", "JDKSAKDJ"), 
  Var2 = c("P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4", 
"Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4", "PE35RV747;P0F071G1G"
)), class = "data.frame", row.names = c("1", "2", "3"))

df2 <- structure(list(Var_x = c("P04TGI7F3", "P030Y7Y11", "PE35RV747", 
"Q2UKLVVX4"), Var_y = c("good", "normal", "bad", "normal")), 
     class = "data.frame", row.names = c("1", 
"2", "3", "4"))
0 голосов
/ 31 января 2019

Вот идея через tidyverse.Мы разделяем строки, объединяем второй фрейм данных и снова объединяем на основе Var1,

library(tidyverse)

df1 %>% 
 separate_rows(Var2) %>% 
 left_join(df2, by = c('Var2' = 'Var_x')) %>% 
 group_by(Var1) %>% 
 summarise_all(funs(paste(., collapse = ';')))

, что дает

# A tibble: 3 x 3
  Var1     Var2                                    Var_y                 
  <fct>    <chr>                                   <chr>                 
1 JDKSAKDJ PE35RV747;P0F071G1G                     bad;NA                
2 ODJSMDK  Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4 normal;NA;bad;normal  
3 SJDJWK   P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal

Если вы это сделаетене желая включать NAs, мы можем опустить его перед присоединением (как упоминает @akrun), т.е.

df1 %>% 
 separate_rows(Var2) %>% 
 filter(Var2 %in% df2$Var_x) %>% 
 left_join(df2, by = c('Var2' = 'Var_x')) %>% 
 group_by(Var1) %>% 
 summarise_all(funs(paste(., collapse = ';')))

, что дает

# A tibble: 3 x 3
  Var1     Var2                                    Var_y                 
  <fct>    <chr>                                   <chr>                 
1 JDKSAKDJ PE35RV747                               bad                   
2 ODJSMDK  Q2UKLVVX4;PE35RV747;Q2UKLVVX4           normal;bad;normal     
3 SJDJWK   P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
0 голосов
/ 31 января 2019

Игра с data.table

df2[df1[, unlist(tstrsplit(Var2, ";")), Var1], 
    on = .(Var_x = V1)
    ][,
      lapply(.SD, function(x) paste(x[!is.na(x)], collapse = ";")), 
      by = Var1
      ]

       Var1                                   Var_x                  Var_y
1:   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
2:  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4      normal;bad;normal
3: JDKSAKDJ                     PE35RV747;P0F071G1G                    bad
0 голосов
/ 31 января 2019

Используя базу R, проходите через Var2, делитесь на ";", затем match :

df1$Var3 <- sapply(df1$Var2, function(i){
  paste(df2$Var_y[ match(unlist(strsplit(i, split = ";")), df2$Var_x) ], collapse = ";")
})

#       Var1                                    Var2                   Var3
# 1   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
# 2  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4   normal;NA;bad;normal
# 3 JDKSAKDJ                     PE35RV747;P0F071G1G                 bad;NA

Примечание: Я знаю, что мой вывод имеет NAв Var3, и ожидаемый результат OP не.Но я предпочел сохранить NA, чтобы мы могли сопоставлять каждую «плохую / нормальную» с соответствующей строкой по позиции в исходной строке.Конечно, если OP желает, их можно удалить, используя na.omit:

df1$Var3 <- sapply(df1$Var2, function(i){
  paste(na.omit(df2$Var_y[ match(unlist(strsplit(i, split = ";")), df2$Var_x) ]), collapse = ";")
})
#       Var1                                    Var2                   Var3
# 1   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
# 2  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4      normal;bad;normal
# 3 JDKSAKDJ                     PE35RV747;P0F071G1G                    bad
...