Измените заменяющее значение совпадения с регулярным выражением в R - PullRequest
0 голосов
/ 30 января 2020

Я работал с PDF в формате R, и данные были представлены в различных форматах. Я хотел преобразовать данные в окончательный фрейм данных; сейчас он в формате chr. Самый простой способ поместить это в фрейм данных - это разделить пробел и затем загрузить его. Все данные выглядят следующим образом; 611 элементов в длинной строке.

enter image description here

2019-02-05 1-02/05/2019-123456-A  Thorton, Billy Bob         W123455834   XXX-XX-1776 ALEXANDER      HAMILTON
2019-02-08 1-02/08/2019-876543-B  Dern, Laura         P98765432   XXX-XX-1789 BETSY      ROSS

Данные в формате выше создают некоторые проблемы:

  1. Пространство между Билли Бобом вызовет дополнительное разделение в данных; у нас просто есть одно поле имени. После того, как они объединены, мы можем легко удалить запятую.
  2. Пробелы между разделителями могут быть различными.
  3. Остальные коды представляют собой буквенные цифры c.

В этом посте я покажу вам несколько кодов и советов регулярных выражений, таких как группировки, изменение регистра и оглядываясь назад, на заданные c группы с помощью расширенного режима Perl:

  1. Создать одно имя из Билли Боба
  2. Конвертировать только имена в нижний регистр для дополнительной простоты обработки позже. Если мы хотим, чтобы все было в нижнем регистре, просто используйте функцию tolower().

Решение было основано на этом посте, я расширяю его, чтобы сделать его более обобщенным c: gsub ошибка при переходе с верхнего на нижний регистр в R

Ответы [ 2 ]

0 голосов
/ 30 января 2020

Используя Lines в примечании в конце, прочитайте его в L, замените повторяющиеся пробелы одним пробелом и затем используйте strcapture с указанным шаблоном. Обратите внимание, что \d соответствует di git, \D соответствует non-di git, а \S соответствует непробельному символу. Пакеты не используются.

L <- readLines(textConnection(Lines))
L <- gsub("  +", " ", L)

pat <- "^(\\S+) (\\S+) (.*) (\\D\\d+) (\\S+) (\\S.*)$"
strcapture(pat, L, proto = list(date = character(0), 
  key = character(0), name1 = character(0), driver = character(0), 
  code = character(0), name2 = character(0)))

предоставление:

        date                   key              name1     driver        code
1 2019-02-05 1-02/05/2019-123456-A Thorton, Billy Bob W123455834 XXX-XX-1776
2 2019-02-08 1-02/08/2019-876543-B        Dern, Laura  P98765432 XXX-XX-1789
               name2
1 ALEXANDER HAMILTON
2         BETSY ROSS

Примечание

Lines <- "2019-02-05 1-02/05/2019-123456-A  Thorton, Billy Bob         W123455834   XXX-XX-1776 ALEXANDER      HAMILTON
2019-02-08 1-02/08/2019-876543-B  Dern, Laura         P98765432   XXX-XX-1789 BETSY      ROSS"
0 голосов
/ 30 января 2020

Первым шагом является объединение всех вхождений двух имен (Билли Боб, Джимм ie Сью и др. c.) В одно имя, чтобы мы получили Thorton,BillyBob, а затем мы можем разделить пробел.

Шаблон, который мы ищем - lowercase space Uppercase. Для этого используется следующее регулярное выражение:

pattern = stringr::regex("([a-z])( )([A-Z][a-z])")
data_join = gsub(pattern=pattern, replacement='\\1\\3', x=data, perl=TRUE)

Мы используем () в регулярном выражении для создания трех группировок: по одной для каждого элемента совпадения. При использовании gsub(), указав replace='\\1\\3', мы говорим регулярному выражению оглянуться назад и использовать 1-й и 3-й элемент регулярного выражения в качестве замены и пропустить второй, который является пробелом для объединения.

Чтобы сделать все имена строчными, нам нужно исключить буквы в буквенно-цифровых цифрах, а также шаблоны 'XXX'.

pattern_low = stringr::regex("(([A-z]){2,}[^XXX-XX-])")
data_low = gsub(pattern=pattern_low, perl = T, replacement ='\\L\\1', x=data_join)

Анализ регулярного выражения: часть ([A-z]){2,} ищет минимум две буквы вместе, чтобы решить проблему alphanumeri c. [^XXX-XX-] говорит ему исключить эти случаи X s. Кроме того, мы добавляем дополнительный набор () вокруг всего этого, чтобы сделать его одной группой.

При замене мы используем \\L, чтобы указать более низкое значение, и \\1, чтобы применить его ко всему группа. Я попробовал несколько групп, как в первом случае, и это не сработало.

Теперь мы можем разбить и загрузить его в кадр данных:

# put it in a data frame
df_all = data_low %>% strsplit(split = "\\s+")

Добавление + позволяет это обрабатывать различные пробелы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...