Извлечение соответствующей информации из текста в R - регулярное выражение - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь извлечь некоторую информацию из текстового документа. Я преобразовал этот текстовый документ в фрейм данных, используя pdftext(). Теперь я хотел бы извлечь информацию, которую я ищу. Ниже приведен код для создания фрейма данных, подобного моему:

text <- data.frame(page = c(1,1,2,3), sen = c(1,2,1,1), text = c("Dear Mr case 1","the value of my property is £500,000.00 and it was built in 1980", 
                                                             "The protected percentage is 0% for 2 years", "The interest rate is fixed for 2 years at 4.8%"))

Из приведенного выше кадра данных мне нужно извлечь следующее:

1: Пол человека. В этом случае это будет мужчина (смотрит на мистера)

2: число, представляющее значение свойства. в этом случае будет £ 500 000,00.

3: Защищенное процентное значение, которое в нашем случае будет 0%.

4: значение процентной ставки, в нашем случае это 4,8%.

В идеале я хотел бы вывести фрейм данных, как показано ниже:

enter image description here

Даже если я смогу извлечь эти фрагменты информации отдельно, это все еще достаточно хорошо. Я, вероятно, могу использовать регулярное выражение, сказать ему, чтобы найти шаблон, такой как «Защищенный процент», а затем дать мне число, которое появляется сразу после того, как он находит этот шаблон. Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Вот частичное решение: регулярное выражение для каждого блока, который вы хотите извлечь.Возможно, вам придется скорректировать регулярное выражение или то, как вы складываете вещи во фрейм данных, но это должно помочь вам.Обратите внимание, что пакет R stringr использует регулярное выражение ICU и требует экранирования с двойной обратной косой чертой.

p_load(tidyverse)

ttt <- str_flatten(text$text)

# gender
gender_regex <- c("M.s*")
gender <- str_match(ttt, gender_regex) 

.: любой символ (т. Е. r из * 1009)* или Mrs, или s из Ms)
*: повторите s 0 или более раз столько раз, сколько возможно (например, 1 s от Mrs или 2 отMiss)

# number property value
propval_regex <- regex("\U00A3\\d\\S++\\s")
property_value <- str_match(ttt, propval_regex) %>%
  str_trim()

\U00A3: гекс в юникоде для знака британского фунта
\\d: любое число
\\S: любой непробельный символ (т. Е. Включает тысячу и десятичное числоразделители)
++: совпадение 1 или более раз
\\s: пробельный символ

# protected percentage value and interest rate
# regex for all percentages
r <- "\\d++\\.?+\\d?+\\%"

# vector of matches
percents <- str_match_all(ttt, r) %>%
  flatten_chr()

# each as its own variable
protected_percentage_value <- percents[1]
interest_rate <- percents[2]

\\d: любое число
++: повторение 1 или более раз
\\.: десятичный разделитель
?+: повтор 0 или один раз
\\%: знак процента

0 голосов
/ 10 мая 2018

Предполагая, что вы можете получить все части вашего массива R в одну строку, это регулярное выражение выполнит эту работу (установите его без учета регистра):

dear\s+(mr|mrs|miss|ms)\b[^£]+(£[\d,.]+)(?:\D|\d(?![\d.]*%))+([\d.]+%)(?:\D|\d(?![\d.]*%))+([\d.]+%)

Матчи в группах захвата 1, 2, 3 и 4.

Вот демоверсия (посмотрите на панель матчей справа): https://regex101.com/r/OcVN5r/1

Я действительно не знаю R, но я понимаю, что вы можете сделать что-то вроде:

regmatches(subject, 
gregexpr("dear\\s+(mr|mrs|miss|ms)\\b[^£]+(£[\\d,.]+)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)",
subject, perl=TRUE, ignore.case=TRUE));

Но я оставляю детали R на ваше усмотрение.

РЕДАКТИРОВАТЬ: Может быть, это будет работать в R:

matches <- gregexpr("dear\\s+(mr|mrs|miss|ms)\\b[^£]+(£[\\d,.]+)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)", subject, perl=TRUE, ignore.case=TRUE);
result <- lapply(matches, function(m) attr(m, "capture.start")[,1])
for (i in seq_along(result))
  attr(result[[i]], "match.length") <- attr(matches[[i]], "capture.length")[,1]
result
...