Регулярное выражение не работает в R, но работает на веб-сайте.Добыча текста - PullRequest
0 голосов
/ 10 мая 2018

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

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%"))

регулярное выражение, работающее на веб-сайте:https://regex101.com/r/OcVN5r/2

Ниже приведены коды R, которые я пробовал до сих пор, и ни одна из них не работает.

library(stringr)
patt = "dear\\s+(mr|mrs|miss|ms)\\b[^£]+(£[\\d,.]+)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)"
str_extract(text, patt)
grepl(pattern = patt, x = text)

Я получаю сообщение о том, что регулярное выражение неверно, но оно работает на веб-сайте.Не уверен, как заставить его работать в р.В основном я пытаюсь извлечь куски информации из текста.Ниже приведены подробности: Из приведенного выше кадра данных мне нужно извлечь следующее:

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

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

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

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

Ответы [ 2 ]

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

Я думаю, проблема в том, что ваше регулярное выражение не дает альтернативных или "ИЛИ" совпадений. См. Ниже на основе вашего списка пули

library(stringi)
rgx <- "(?<=dear\\s?)(m(r(s)?|s|iss))|\\p{S}([0-9]\\S+)|([0-9]+)((\\.[0-9]{1,})?)\\%"
stri_extract_all_regex(
   text$text, rgx, opts_regex = stri_opts_regex(case_insensitive = T)
) %>% unlist()

Что дает

[1] "Mr"          "£500,000.00"      "0%"          "4.8%" 

Шаблон говорит:

  • "(?<=dear\\s?)(m(r(s)?|s|iss))" = найти совпадение, в котором слово "дорогой" появляется перед "г-ном, мс, миссис или мисс" ... но не захватывать дорогой или ведущий пробел
  • | = ИЛИ
  • "\\p{S}([0-9]\\S+)" = найти совпадение, в котором после символа появляется последовательность чисел (см.? Stringi-search-charclass), пока не появится пробел. Но в начале он должен иметь символ
  • | = ИЛИ
  • "([0-9]+)((\\.[0-9]{1,})?)\\%" = найти совпадение, в котором число встречается один или несколько раз, может иметь десятичную дробь с цифрами после него, но оканчивается знаком процента
0 голосов
/ 10 мая 2018

Думаю, вы можете сделать это с помощью функции regexpr.

Например:

text = "Dear Mr case 1, the value of my property is £500,000.00 and it was built in 1980, The protected percentage is 13% for 2 years, The interest rate is fixed for 2 years at 4.8%";

grps <- regexpr (pattern=patt, text = text, perl=TRUE, ignore.case=TRUE);

start_idx <- attr (grps, "capture.start");
end_idx   <- start_idx + attr (grps, "capture.length");

substring (text = text, first = start_idx, last = end_idx); 

Это соответствует: [1] "Mr " "£500,000.00 " "13% " "4.8%"

Из руководства:

regexpr возвращает целочисленный вектор такой же длины, что и текст, задающий начальную позицию первого совпадения, или -1, если такового нет, с атрибутом «match.length»,целочисленный вектор, дающий длину сопоставленного текста (или -1 для несоответствия).Позиции и длины совпадений указываются в символах, если только useBytes = TRUE не используется, когда они представлены в байтах (как и для сопоставления только в ASCII: в любом случае для результата устанавливается атрибут useBytes со значением TRUE).Если используется именованный захват, существуют дополнительные атрибуты «capture.start», «capture.length» и «capture.names».

gregexpr возвращает список такой же длины, что и каждый текстэлемент которого имеет ту же форму, что и возвращаемое значение для regexpr, за исключением того, что даны начальные позиции каждого (непересекающегося) совпадения.

В вашем случае, я думаю, вам нужно вставить строки вместеиспользуя

full_line <- paste (text[,"text"], collapse=" ");

Затем примените regexpr к full_line

...