从R

时间:2015-10-01 14:49:39

标签: regex r gsub

我对正则表达式比较陌生,而且我正陷入死胡同。我有一个数据框,其列如下所示:

year1
GMM14_2000_NGVA
GMM14_2001_NGVA
GMM14_2002_NGVA
...
GMM14_2014_NGVA

我试图在字符串中间提取年份(2000,2001等)。到目前为止,这是我的代码

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

返回数字,但它也返回14作为字符串的一部分:

142000
142001

有关如何从模式中排除14或如何更有效地提取年份信息的任何想法?

由于

5 个答案:

答案 0 :(得分:7)

使用stringi包,以下是一种方法。假设年份是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"

答案 1 :(得分:6)

使用以下gsub

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

请参阅IDEONE demo

正则表达式分解:

...匹配

  • ^[^_]*_ - 字符串开头的_以外的0个或多个字符以及_
  • | - 或......
  • _[^_]*$ - _以及_以外的0个或更多字符到字符串末尾

并删除它们。

作为替代方案,

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

Perl-like regex匹配用下划线括起来的4位子字符串。

答案 2 :(得分:2)

base-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我们收集列表中每个向量的第二个元素,即下划线之间的年份。

答案 3 :(得分:2)

您可以使用sub。

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

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

这将提取开始和结束分隔符之间存在的所有字符。这里的开始和结束分隔符是下划线。

语法:

extract_a(start, end, string)

答案 4 :(得分:0)

我从未使用过R,但对regexp有很深的经验。

习惯用法是使用匹配。

对于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中测试所有这些。