R中的重叠比赛

时间:2014-09-12 02:56:48

标签: regex r string dna-sequence stringi

我已搜索并能够找到此forum discussion以实现重叠匹配的效果。

我还发现了以下SO提到找到执行此任务的索引的问题,但是无法找到任何关于在R语言中抓取重叠匹配的简洁信息。

我可以在大多数任何支持(PCRE)的语言中执行此任务,方法是在前瞻内部实现捕获组以捕获重叠匹配时使用正向前瞻断言。

但是,虽然实际执行此操作的方式与其他语言相同,但在R中使用perl=T时,结果不会产生。

> x <- 'ACCACCACCAC'
> regmatches(x, gregexpr('(?=([AC]C))', x, perl=T))[[1]]
[1] "" "" "" "" "" "" ""

使用stringistringr包也是如此。

> library(stringi)
> library(stringr)
> stri_extract_all_regex(x, '(?=([AC]C))')[[1]]
[1] "" "" "" "" "" "" ""
> str_extract_all(x, perl('(?=([AC]C))'))[[1]]
[1] "" "" "" "" "" "" ""

执行此操作时应返回的正确结果为:

[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

修改

  1. 我很清楚regmatches在捕获的匹配项中效果不佳,但完全会导致重新匹配中出现此行为,为什么没有返回结果? 我正在寻找一个有点详细的答案

  2. stringistringr包是否无法通过regmatches执行此操作?

  3. 请随时添加我的回答或提出与我找到的不同的解决方法。

6 个答案:

答案 0 :(得分:7)

就解决方法而言,这就是我提出的用于提取重叠匹配的内容。

> x <- 'ACCACCACCAC'
> m <- gregexpr('(?=([AC]C))', x, perl=T)
> mapply(function(X) substr(x, X, X+1), m[[1]])
[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

请随意添加或评论更好的方法来执行此任务。

答案 1 :(得分:6)

标准regmatches对捕获的匹配(特别是同一字符串中的多个捕获的匹配)不起作用。在这种情况下,因为你匹配&#34;向前看(忽略捕获),匹配本身是零长度。还有regmatches()<-函数可以说明这一点。 Obseerve

x <- 'ACCACCACCAC'
m <- gregexpr('(?=([AC]C))', x, perl=T)
regmatches(x, m) <- "~"
x
# [1] "~A~CC~A~CC~A~CC~AC"

注意如何保留所有字母,我们只是将零长度匹配的位置替换为我们可以观察到的内容。

我创建了一个regcapturedmatches()函数,我经常用它来完成这些任务。例如

x <- 'ACCACCACCAC'
regcapturedmatches(x, gregexpr('(?=([AC]C))', x, perl=T))[[1]]

#      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
# [1,] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

gregexpr正在抓取所有数据,所以如果你不想使用这个辅助函数,你可以从生活中提取它。

答案 2 :(得分:4)

提取我过去所做的相同信息的另一种迂回方式是将"match.length"替换为"capture.length"

x <- c("ACCACCACCAC","ACCACCACCAC")
m <- gregexpr('(?=([AC]C))', x, perl=TRUE)
m <- lapply(m, function(i) {
       attr(i,"match.length") <- attr(i,"capture.length")
       i
     })
regmatches(x,m)

#[[1]]
#[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"
#
#[[2]]
#[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

答案 3 :(得分:4)

这不是一个正则表达式解决方案,并没有真正回答任何更重要的问题,但您也可以通过一次使用两个字符的子字符串然后删除不需要的CA来获得所需的结果元素。

x <- 'ACCACCACCAC'
y <- substring(x, 1:(nchar(x)-1), 2:nchar(x))
y[y != "CA"]
# [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

答案 4 :(得分:4)

使用前瞻部分中的捕获组的stringi解决方案:

> stri_match_all_regex('ACCACCACCAC', '(?=([AC]C))')[[1]][,2]
## [1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"    

答案 5 :(得分:1)

另一个答案,基于@ hwnd自己的答案(原始版本不允许可变长度捕获区域),只使用内置R函数:

> x <- 'ACCACCACCAC'
> m <- gregexpr('(?=([AC]C))', x, perl=T)[[1]]
> start <- attr(m,"capture.start")
> end <- attr(m,"capture.start") + attr(m,"capture.length") - 1
> sapply(seq_along(m), function(i) substr(x, start[i], end[i]))
[1] "AC" "CC" "AC" "CC" "AC" "CC" "AC"

非常难看,这就是stringr等软件包存在的原因。