Подтвердить что ты не робот

R grep: сопоставить одну строку с несколькими шаблонами

В R grep обычно соответствует вектору нескольких строк в отношении одного регулярного выражения.

В: Есть ли возможность сопоставить одну строку с несколькими регулярными выражениями? (без прокрутки по каждому шаблону регулярного выражения)?

Некоторая предыстория:

У меня есть 7000+ ключевых слов в качестве индикаторов для нескольких категорий. Я не могу изменить словарь ключевых слов. Словарь имеет следующую структуру (ключевые слова в столбце 1, номера указывают категории, к которым относятся эти ключевые слова):

ab  10  37  41
abbrach*    38
abbreche    39
abbrich*    39
abend*  37
abendessen* 60  63
aber    20  23  45
abermals    37

Объединение так много ключевых слов с помощью "|" не является возможным (и я не знаю, какой из ключевых слов сгенерировал хит). Кроме того, просто реверсирование "шаблонов" и "строк" ​​не работает, поскольку у шаблонов есть усечения, которые не будут работать наоборот.

[связанный вопрос, другой язык программирования]

4b9b3361

Ответ 1

Как насчет применения функции regexpr над вектором ключевых слов?

keywords <- c("dog", "cat", "bird")

strings <- c("Do you have a dog?", "My cat ate by bird.", "Let get icecream!")

sapply(keywords, regexpr, strings, ignore.case=TRUE)

     dog cat bird
[1,]  15  -1   -1
[2,]  -1   4   15
[3,]  -1  -1   -1

    sapply(keywords, regexpr, strings[1], ignore.case=TRUE)

 dog  cat bird 
  15   -1   -1 

Возвращаемые значения - это позиция первого символа в матче, при этом -1 не означает совпадения.

Если позиция совпадения не имеет значения, вместо этого используйте grepl:

sapply(keywords, grepl, strings, ignore.case=TRUE)

       dog   cat  bird
[1,]  TRUE FALSE FALSE
[2,] FALSE  TRUE  TRUE
[3,] FALSE FALSE FALSE

Обновление:. Это довольно быстро работает в моей системе, даже с большим количеством ключевых слов:

# Available on most *nix systems
words <- scan("/usr/share/dict/words", what="")
length(words)
[1] 234936

system.time(matches <- sapply(words, grepl, strings, ignore.case=TRUE))

   user  system elapsed 
  7.495   0.155   7.596 

dim(matches)
[1]      3 234936

Ответ 2

Чтобы перейти к другому ответу, чтобы преобразовать вывод sapply() в полезный логический вектор, вам нужно дополнительно использовать шаг apply().

keywords <- c("dog", "cat", "bird")
strings <- c("Do you have a dog?", "My cat ate by bird.", "Let get icecream!")
(matches <- sapply(keywords, grepl, strings, ignore.case=TRUE))
#        dog   cat  bird
# [1,]  TRUE FALSE FALSE
# [2,] FALSE  TRUE  TRUE
# [3,] FALSE FALSE FALSE

Чтобы узнать, какие строки содержат какие-либо ключевые слова (шаблоны):

apply(matches, 1, any)
# [1]  TRUE  TRUE FALSE

Чтобы узнать, какие ключевые слова (шаблоны) были сопоставлены в прилагаемых строках:

apply(matches, 2, any)
#  dog  cat bird 
# TRUE TRUE TRUE

Ответ 3

Пакет re2r может соответствовать нескольким шаблонам (параллельно). Минимальный пример:

# compile patterns
re <- re2r::re2(keywords)
# match strings
re2r::re2_detect(strings, re, parallel = TRUE)