【问题标题】:Count the number of overlapping substrings within a string计算字符串中重叠子字符串的数量
【发布时间】:2014-05-24 02:06:43
【问题描述】:

示例:

s <- "aaabaabaa"
p <- "aa"

我想返回 4,而不是 3(即将初始 "aaa" 中的 "aa" 实例数计为 2,而不是 1)。

有什么包可以解决吗?或者有什么办法可以算入R?

【问题讨论】:

  • 我认为OP想要计算s中字符串"aa"的出现次数,计算"aaa"中的两个重叠出现。遗传学/生物导体工具中可能有一些有用的东西。
  • sum(grepl(p, sapply(1:(nchar(s) - 1), function(ii) substr(s, ii, ii + 1))))

标签: string r


【解决方案1】:

我相信

find_overlaps <- function(p,s) {
    gg <- gregexpr(paste0("(?=",p,")"),s,perl=TRUE)[[1]]
    if (length(gg)==1 && gg==-1) 0 else length(gg)
}


find_overlaps("aa","aaabaabaa")  ## 4
find_overlaps("not_there","aaabaabaa") ## 0 
find_overlaps("aa","aaaaaaaa")  ## 7

会做你想做的,这会更清楚地表达为“查找字符串中重叠子字符串的数量”。

这是Finding the indexes of multiple/overlapping matching substrings 的一个细微变化

【讨论】:

  • 我没有看到你也给出了解决方案。我的也可以,但有点笨拙(但可能更透明)。
  • 我需要一种更通用的方法,并发布了使用您的解决方案的答案。我的方法肯定不理想。如果您在自己的帖子中概括您的方法,我将删除我的答案。
【解决方案2】:

substring 在这里可能很有用,因为它获取每对连续的字符。

( ss <- sapply(2:nchar(s), function(i) substring(s, i-1, i)) )
## [1] "aa" "aa" "ab" "ba" "aa" "ab" "ba" "aa"
sum(ss %in% p)
## [1] 4

【讨论】:

  • 无论如何都可以。如果他们愿意,@rawr 可以发布评论作为答案。
【解决方案3】:

我需要一个相关的更一般问题的答案。以下是我对 Ben Bolker 的解决方案的概括:

my.data <- read.table(text = '
  my.string   my.cov
     1.2...        1
     .21111        2
     ..2122        3
     ...211        2
     112111        4
     212222        1
', header = TRUE, stringsAsFactors = FALSE)

desired.result.2ch <- read.table(text = '
  my.string   my.cov   n.11   n.12   n.21   n.22
     1.2...        1      0      0      0      0
     .21111        2      3      0      1      0
     ..2122        3      0      1      1      1
     ...211        2      1      0      1      0
     112111        4      3      1      1      0
     212222        1      0      1      1      3
', header = TRUE, stringsAsFactors = FALSE)

desired.result.3ch <- read.table(text = '
  my.string   my.cov   n.111   n.112   n.121   n.122   n.222   n.221   n.212   n.211
     1.2...        1       0       0       0       0       0       0       0       0
     .21111        2       2       0       0       0       0       0       0       1
     ..2122        3       0       0       0       1       0       0       1       0
     ...211        2       0       0       0       0       0       0       0       1
     112111        4       1       1       1       0       0       0       0       1
     212222        1       0       0       0       1       2       0       1       0
', header = TRUE, stringsAsFactors = FALSE)

find_overlaps <- function(s, my.cov, p) {
    gg <- gregexpr(paste0("(?=",p,")"),s,perl=TRUE)[[1]]
    if (length(gg)==1 && gg==-1) 0 else length(gg)
}

p <- c('11', '12', '21', '22', '111', '112', '121', '122', '222', '221', '212', '211')

my.output <- matrix(0, ncol = (nrow(my.data)+1), nrow = length(p))

for(i in seq(1,length(p))) {
    my.data$p <- p[i]
    my.output[i,1] <- p[i]
    my.output[i,(2:(nrow(my.data)+1))] <-apply(my.data, 1, function(x) find_overlaps(x[1],  x[2],  x[3]))
    apply(my.data, 1, function(x) find_overlaps(x[1],  x[2],  x[3]))
}

my.output
desired.result.2ch
desired.result.3ch

pre.final.output <- matrix(t(my.output[,2:7]), ncol=length(p), nrow=nrow(my.data))

final.output <- data.frame(my.data[,1:2], t(apply(pre.final.output, 1, as.numeric)))
colnames(final.output) <- c(colnames(my.data[,1:2]), paste0('x', p))
final.output

#  my.string my.cov x11 x12 x21 x22 x111 x112 x121 x122 x222 x221 x212 x211
#1    1.2...      1   0   0   0   0    0    0    0    0    0    0    0    0
#2    .21111      2   3   0   1   0    2    0    0    0    0    0    0    1
#3    ..2122      3   0   1   1   1    0    0    0    1    0    0    1    0
#4    ...211      2   1   0   1   0    0    0    0    0    0    0    0    1
#5    112111      4   3   1   1   0    1    1    1    0    0    0    0    1
#6    212222      1   0   1   1   3    0    0    0    1    2    0    1    0

【讨论】:

    【解决方案4】:

    一个整洁,我认为更具可读性的解决方案是

    library(tidyverse)
    PatternCount <- function(text, pattern) {
        #Generate all sliding substrings
        map(seq_len(nchar(text) - nchar(pattern) + 1), 
            function(x) str_sub(text, x, x + nchar(pattern) - 1)) %>%
        #Test them against the pattern
        map_lgl(function(x) x == pattern) %>%
        #Count the number of matches
        sum
    }
    
    PatternCount("aaabaabaa", "aa")
    # 4
    

    【讨论】:

      猜你喜欢
      • 2014-11-01
      • 2018-08-23
      • 1970-01-01
      • 2017-10-20
      • 2015-11-23
      • 1970-01-01
      • 2020-06-02
      • 2023-04-06
      • 2016-05-24
      相关资源
      最近更新 更多