2015-06-23 3 views
8

Запись Karl Broman: https://kbroman.wordpress.com/2015/06/22/randomized-hobbit-2/ заставила меня играть с регулярным выражением и ngrams только для удовольствия. Я попытался использовать регулярное выражение для извлечения 2 грамм. Я знаю, что для этого есть синтаксические анализаторы, но я интересуюсь логикой регулярных выражений (т. Е. Это был вызов, который я не смог выполнить).r ngram extract с regex

Ниже приводится минимальный пример и желаемый результат. Проблема в моей попытке в 2 раза:

  1. Графы (слова) съедаются и недоступны для следующего прохода. Как я могу сделать их доступными для второго прохода? (например, я хочу like быть доступны для like toast после того, как уже было потреблено ранее в I like)

  2. Я не мог сделать пространство между словами, не захвачена (обратите внимание на заднюю белое пространство в моем выходе, даже если я использовано (?:\\s*)). Как я могу не записывать конечные пробелы в n-м (в данном случае втором) слове? Я знаю, что это можно сделать просто с помощью: "(\\b[A-Za-z']+\\s)(\\b[A-Za-z']+)" для 2-грамм, но я хочу расширить решение до n-граммов. PS Я знаю о \\w, но я не рассматриваю символы подчеркивания и числа как части слова, но рассмотрим ' как часть слова.

MWE:

library(stringi) 

x <- "I like toast and jam." 

stringi::stri_extract_all_regex(
    x, 
    pattern = "((\\b[A-Za-z']+\\b)(?:\\s*)){2}" 
) 

## [[1]] 
## [1] "I like " "toast and " 

Желаемая Выход:

## [[1]] 
## [1] "I like" "like toast" "toast and" "and jam" 
+0

Возможно, лучший подход к проблеме № 2: '' (\\ b [A-Za-z '] + \\ s +) {1} (\\ b [A-Za-z'] +) " 'где вы расширяете регулярное выражение, отрегулировав значение 1 на' n-1' –

ответ

6

Вот один из способов использования базы R регулярное выражение. Это можно легко расширить, чтобы обрабатывать произвольные n-граммы. Хитрость заключается в том, чтобы поместить группу захвата внутри положительного прогнозного утверждения, например, (?=(my_overlapping_pattern))

x <- "I like toast and jam." 
pattern <- "(?=(\\b[A-Za-z']+\\b \\b[A-Za-z']+\\b))" 
matches<-gregexpr(pattern, x, perl=TRUE) 
# a little post-processing needed to get the capture groups with regmatches 
attr(matches[[1]], 'match.length') <- as.vector(attr(matches[[1]], 'capture.length')[,1]) 
regmatches(x, matches) 

# [[1]] 
# [1] "I like"  "like toast" "toast and" "and jam" 
+0

. Я думаю, что это связано с будущими поисковиками: http://stackoverflow.com/a/25800334/1000343 Соответствующая терминология, которую я отсутствовала, - это * Перекрывающие совпадения * Спасибо за ответ. –

2

На самом деле, есть приложение для этого:. quanteda пакета (для количественного анализа текстовых данных). Мой соавтор Paul Nulty и я прилагаем все усилия, чтобы улучшить это, но он легко справляется с используемым вами случаем.

install.packages("quanteda") 
require(quanteda) 
x <- "I like toast and jam." 
> ngrams(x, 2) 
## [[1]] 
## [1] "i_like"  "like_toast" "toast_and" "and_jam" 
ngrams(x, n = 2, concatenator = " ", toLower = FALSE) 
## [[1]] 
## [1] "I like"  "like toast" "toast and" "and jam" 

Необязательных регулярных выражений не требуется!

+0

Я уступаю, вы правы в вопросе, но, надеюсь, кто-то, кто ищет вопросы о словах ngrams, найдет это полезным! –

+1

Спасибо, @ Кен-Бенуа, это выглядит как полезный пакет, и я с нетерпением жду его проверки. –

+1

Я использовал это на работе сегодня. Хорошие обновления до пакета. +1 –