Сопоставить строку слов и вернуть несоответствующие слова - PullRequest
4 голосов
/ 28 апреля 2020

Я хотел бы сопоставить строку слов между двумя столбцами и вернуть несоответствующее слово.

Пример кадра данных:

data = data.frame(animal1 = c("cat, dog, horse, mouse", "cat, dog, horse", "mouse, frog", "cat, dog, frog, cow"), animal2 = c("dog, horse, mouse", "cat, horse", "frog", "cat, dog, frog"))

Я хотел бы добавить новый столбец "unique_animal ", с результирующим фреймом данных:

                 animal1           animal2 unique_animal
1 cat, dog, horse, mouse dog, horse, mouse           cat
2        cat, dog, horse        cat, horse           dog
3            mouse, frog              frog         mouse
4    cat, dog, frog, cow    cat, dog, frog           cow

Я пробовал код из этого вопроса: Соответствие одинаковых строковых векторов и возврат несоответствующего элемента

library(qualV)
common <- function(a,b) {
  a2 <- strsplit(a,'')[[1]]
  b2 <- strsplit(b,'')[[1]]
  if(length(a2) < length(b2)) {
    a2[(length(a2)+1):length(b2)] <- ' '
  } else if(length(a2) > length(b2)) {
    b2[(length(b2)+1):length(a2)] <- ' '
  }
  LCS(a2,b2)
}

result <- NULL
data$animal1 <- as.character(data$animal1)
data$animal2 <- as.character(data$animal2)
for (i in 1:nrow(data)){
  data_temp <- data[i,]
  z <- common(data_temp$animal1,data_temp$animal2)
  paste0(z$LCS, collapse = '') # common string
  x <- z$a[which(!seq(1,max(z$va)) %in% z$va)] # non-matching elements in `a`
  x <- paste(x, collapse='' )
  data_temp$unique_animal <- x
  result <- rbind(data_temp, result)
}

Который производит это:

                 animal1           animal2 unique_animal
1 cat, dog, horse, mouse dog, horse, mouse         cat, 
2        cat, dog, horse        cat, horse         , dog
3            mouse, frog              frog       mouse, 
4    cat, dog, frog, cow    cat, dog, frog             ,

Запятые не проблема, я могу легко удалить их. Но это не работает, когда несоответствующее слово находится в конце строки. По какой-то причине он не учитывает общее количество элементов в этом случае. Есть идеи, как изменить этот код, чтобы он этого не делал? Или альтернативный метод?

Спасибо!

1 Ответ

4 голосов
/ 28 апреля 2020

После разделения столбцов на ,\\s* мы можем использовать map2 для сравнения соответствующих list элементов с setdiff

library(dplyr)
library(purrr)
library(stringr)
data %>%
   mutate(unique_animal = map2_chr(strsplit(as.character(animal1), ",\\s+"), 
                 strsplit(as.character(animal2), ",\\s+"), 
             ~ str_c(setdiff(.x, .y), collapse=", ")))
#                 animal1           animal2 unique_animal
#1 cat, dog, horse, mouse dog, horse, mouse           cat
#2        cat, dog, horse        cat, horse           dog
#3            mouse, frog              frog         mouse
#4    cat, dog, frog, cow    cat, dog, frog           cow
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...