2015-10-01 7 views
4

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

year1 
GMM14_2000_NGVA 
GMM14_2001_NGVA 
GMM14_2002_NGVA 
... 
GMM14_2014_NGVA 

Я пытаюсь извлечь год в середине строки (2000,2001 и т.д.). Это мой код до сих пор

gsub("[^0-9]","",year1)) 

Который возвращает номер, но он также возвращает 14, который является частью строки:

142000 
142001 

Любая идея о том, чтобы исключить 14 из шаблона или как более эффективно извлекать годовую информацию?

Благодаря

ответ

5

Используйте следующие gsub:

s = "GMM14_2002_NGVA" 
gsub("^[^_]*_|_[^_]*$", "", s) 

См IDEONE demo

Разбивка регулярное выражение:

Match ...

  • ^[^_]*_ - 0 или больше, чем другие _ символы от начала строки и _
  • | - или ...
  • _[^_]*$ - это _ и 0 или больше символов, кроме _ до конца строки

и удалите их.

В качестве альтернативы,

library(stringr) 
str_extract(s,"(?<=_)\\d{4}(?=_)") 

В случае, если Perl-подобные регулярное выражение соответствует 4-значной подстроке, заключенное подчеркивание.

+0

Обратите внимание, что ваше регулярное выражение в GSUB соответствует каждому символу, который не является цифрой и удаляет его от входа. Вот почему у вас были все цифры от ввода слева в результате. –

6

Использование stringi package, следующее в одну сторону. Предполагается, что год состоит из 4 цифр. Поскольку вы указываете номер цифры, это довольно прямолинейно.

library(stringi) 

x <- c("GMM14_2000_NGVA", "GMM14_2001_NGVA") 

stri_extract_last(x, regex = "\\d{4}") 
#[1] "2000" "2001" 

или

stri_extract_first(x, regex = "\\d{4}") 
#[1] "2000" "2001" 
+0

Существует одна потенциальная проблема с этим регулярным выражением: поскольку он не учитывает контекст, будет извлечена любая последняя или первая 4-значная последовательность. –

+0

@stribizhev Уверенная вещь. Увидев образцы выборочных данных, я решил выбрать этот путь. Если есть другие шаблоны, это не путь. Спасибо, что оставили комментарий. :) – jazzurro

+1

Вы также можете использовать прямую функцию 'stri_extract_last_regex (x," \\ d + ")'. Должен быть быстрее, так как он позволяет избежать некоторых проверок. –

2

Другой вариант в базовой-R будет strsplit с использованием @jazzurro «ы данных:

x <- c("GMM14_2000_NGVA", "GMM14_2001_NGVA") 

vapply(strsplit(x, '_'), function(x) x[2], character(1)) 
[1] "2000" "2001" 

strsplit расколы каждый элемент вектора x на подчеркиванием _ и выводит список той же длины, что и длина x. Используя vapply, мы собираем второй элемент каждого вектора в списке, то есть год между символами подчеркивания.

2

Вы можете использовать вспомогательные устройства.

sub(".*_(\\d{4})_.*", "\\1", x) 

или

devtools::install_github("Avinash-Raj/dangas") 
library(dangas) 
extract_a("_", "_", x) 

Это было бы извлечь все символы, присутствующие в промежутке между начальным и конечным разделителями. Здесь начальный и конечный разделитель является символом подчеркивания.

Синтаксис:

extract_a(start, end, string) 
0

Я никогда не использовал R, но имел большой опыт с регулярными выражениями.

Идиоматически правильный способ заключается в использовании соответствия.

Для R должно быть regmatches:

Использование regmatches получить фактические подстроки, совпавшие с регулярным выражением . В качестве первого аргумента передайте тот же ввод, который вы передали в regexpr или gregexpr. В качестве второго аргумента передайте вектор , возвращаемый regexpr или gregexpr. Если вы передадите вектор из regexpr , то regmatches вернет вектор символов со всеми строками, которые были сопоставлены . Этот вектор может быть короче входного вектора, если в некоторых элементах найдено совпадение . Если вы передадите вектор из regexpr, то regmatches вернет вектор с таким же числом элементов в качестве входного вектора. Каждый элемент является символьным вектором с всеми совпадениями соответствующего элемента во входном векторе или NULL, если элемент не имеет совпадений.

>x <- c("abc", "def", "cba a", "aa") 
> m <- regexpr("a+", x, perl=TRUE) 
> regmatches(x, m) 
[1] "a" "a" "aa" 

В случае, вы должны быть:

m <- regexpr("\d{4}", year1, perl=TRUE) 
regmatches(year1, m) 

В случае, если вы можете иметь еще 4 цифры подряд в одной и той же строки, вы можете использовать non capturing groups. Возможно, как это:

"(?:_)\d{4}(?:_)" 

К сожалению, нет возможности проверить все это в R.