Фильтровать фрейм данных на основе совпадающих значений (точных) между двумя столбцами

#r #dataframe #match

#r #фрейм данных #совпадение

Вопрос:

У меня есть фрейм данных, содержащий два столбца. Один столбец содержит список предложений, другой столбец содержит слова. Например:

 words   sentences
loose   Loose connection several times a day on my tablet.  
loud    People don't speak loud or clear enough to hear voicemails
vice    I strongly advice you to fix this issue
advice  I strongly advice you to fix this issue
  

Теперь я хочу отфильтровать этот фрейм данных таким образом, чтобы я получал только те строки, в которых есть слова, которые точно совпадают со словами в предложении:

 words   sentences
loose   Loose connection several times a day on my tablet.  
loud    People don't speak loud or clear enough to hear voicemails
advice  I strongly advice you to fix this issue   
  

Слово «vice» не соответствует точно, поэтому его необходимо удалить. У меня почти 20 тыс. строк в фрейме данных. Может кто-нибудь подсказать мне, какой метод использовать для выполнения этой задачи, чтобы я не сильно терял производительность.

Ответ №1:

Используя:

 library(stringi)
df[stri_detect_regex(tolower(df$sentences), paste0('\b',df$words,'\b')),]
  

вы получаете:

    words                                                  sentences
1  loose         Loose connection several times a day on my tablet.
2   loud People don't speak loud or clear enough to hear voicemails
4 advice                    I strongly advice you to fix this issue
  

Объяснение:

  • Преобразуйте заглавные буквы в предложениях в строчные буквы с tolower помощью .
  • Создайте вектор регулярных выражений с paste0 помощью обертывания слов words в wordboundaries ( \b ).
  • Используйте stri_detect_regex stringi-package, чтобы увидеть, в каких строках нет совпадений, что приводит к logicalvector со TRUE FALSE значениями amp; .
  • Подмножество с логическим вектором.

В качестве альтернативы вы также можете использовать str_detect из stringr пакета (который на самом деле является оболочкой вокруг stringi пакета):

 library(stringr)
df[str_detect(tolower(df$sentences), paste0('\b',df$words,'\b')),]
  

Используемые данные:

 df <- structure(list(words = c("loose", "loud", "vice", "advice"), 
                     sentences = c("Loose connection several times a day on my tablet.", 
                                   "People don't speak loud or clear enough to hear voicemails", 
                                   "I strongly advice you to fix this issue", "I strongly advice you to fix this issue")), 
                .Names = c("words", "sentences"), class = "data.frame", row.names = c(NA, -4L))
  

Ответ №2:

Вы можете попробовать что-то вроде следующего:

 df[apply(df, 1, function(x) tolower(x[1]) %in% tolower(unlist(strsplit(x[2], split='\s ')))),]

df
   words                                                sentences
1  loose       Loose connection several times a day on my tablet.
2   loud People dont speak loud or clear enough to hear voicemail
4 advice          advice  I strongly advice you to fix this issue
  

Комментарии:

1. Этот подход быстрее, чем использование str_detect, поэтому принимаю это как ответ.

Ответ №3:

Наиболее простым решением является использование пакета stringr:

 df<- data.frame(words=c("went","zero", "vice"), sent=c("a man went to the park","one minus one is 0","any advice?"))

df$words <- paste0(" ",df$words," ")
df$sent <- paste0(" ",df$sent," ")


df$match <- str_detect(df$sent,df$words)

df.res <- df[df$match > 0,]
df.res$match<-NULL
df.res
  

Комментарии:

1. Это не дает предпочтительного вывода для данных OP.

2. Сейчас работает, но это, безусловно, уже не самое простое решение, imo. Более того, содержимое sent столбца изменилось, что не входило в намерения OP.

3. По сути, ваша версия — более элегантная версия моей, но я только недавно начал развивать свои навыки R самостоятельно!

4. Я не собираюсь быть враждебным, но, пожалуйста, учтите следующее: судя по желаемому результату, совпадение без учета регистра — это то, что нужно OP. Что касается добавления или нет к другому ответу: сначала вы использовали stri_extract в своем ответе, и эта версия вашего ответа не давала желаемого результата. Вы переключились на str_detect way после того, как я опубликовал свой ответ. (кстати: я не понизил голос)

5. Я отвечал кому-то еще, кто с тех пор удалил свои комментарии, вы вообще не были враждебны