#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. Я отвечал кому-то еще, кто с тех пор удалил свои комментарии, вы вообще не были враждебны