我对正则表达式比较陌生,而且我正陷入死胡同。我有一个数据框,其列如下所示:
year1
GMM14_2000_NGVA
GMM14_2001_NGVA
GMM14_2002_NGVA
...
GMM14_2014_NGVA
我试图在字符串中间提取年份(2000,2001等)。到目前为止,这是我的代码
gsub("[^0-9]","",year1))
返回数字,但它也返回14作为字符串的一部分:
142000
142001
有关如何从模式中排除14或如何更有效地提取年份信息的任何想法?
由于
答案 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中测试所有这些。