如何确定字符串中每个位置的代码字频率

时间:2017-12-20 15:27:19

标签: r

我有几个可变长度的字符串,例如:

sequences <- c("ABCDEFGH", "FGHABCDEF")

我还有一个“密钥”,它是上述这些序列的重叠子字符串的集群版本。

key <- data.frame(codewords = c(1, 2, 3, 4), 
       substrings = c("BCD, FGH", "CDE, EFG", "ABC, DEF", "GHA, HAB"))

我想从每个序列的每个位置开始查看这些codewords的频率。

例如,我看到代码字3从字符串的位置1开始一次(ABC),代码字1从字符串的位置2开始一次,等等......

我想看一下所有序列中每个码字的起始位置的频率。

对于这个例子,我正在寻找如下输出:

StartingPosition     Codeword    Occurences
1     1     1
1     2     0
1     3     1
1     4     0
2     1     1
2     2     0
2     3     0
2     4     1
3     1     0
3     2     1
3     3     0
3     4     1
4     1     0
4     2     0
4     3     2
4     4     0

但是,我的实际数据有100个码字和10000多个序列。我正在寻找一种计算效率高的方法。在这种情况下,起始位置的最大数量始终是最长的序列(在这种情况下为9个字母)减去3 + 1 = 7,因为所有的代码字都是长度为3.代码字长度也可供我使用,所以无论代码字长度如何,我都希望能够做到这一点。

如果需要,请随时要求澄清!

由于

1 个答案:

答案 0 :(得分:2)

这是我的看法:

key$substrings <- sub(",\\s", "|", key$substrings)
res <- lapply(key$substrings, function(x) {
  x <- gregexpr(x, text = sequences)
  setNames(as.data.frame(table(unlist(x))), c("StartingPosition", "Occurences"))
})

res <- do.call(rbind, Map(cbind, res, 
                          codeword = key$codewords, 
                          substrings = key$substrings))
res <- subset(res, StartingPosition != -1)

#   StartingPosition Occurences codeword substrings
#1                 1          1        1    BCD|FGH
#2                 2          1        1    BCD|FGH
#3                 5          1        1    BCD|FGH
#4                 6          1        1    BCD|FGH
#5                 3          1        2    CDE|EFG
#6                 6          1        2    CDE|EFG
#7                 1          1        3    ABC|DEF
#8                 4          2        3    ABC|DEF
#9                 7          1        3    ABC|DEF
#11                2          1        4    GHA|HAB

之后您可以轻松填写​​0次。

步骤基本上是:

  • 使用逻辑OR而不是逗号分隔
  • key$substrings转换为正则表达式的可用模式
  • 使用gregexpr确定每个序列中每个子串模式的起始位置
  • 提取所有起始位置并计算每个子串/代码字的出现次数
  • 将代码字数字和子字符串添加到结果data.frame
  • 删除Startingposition为-1的条目,因为这表示找不到给定代码字匹配

如果我们在字符串中有多个代码字出现,这将为您提供所有起始位置。例如:

sequences <- "ABCDEFABC"

res <- lapply(key$substrings, function(x) {
  x <- gregexpr(x, text = sequences)
  setNames(as.data.frame(table(unlist(x))), c("StartingPosition", "Occurences"))
})

res <- do.call(rbind, Map(cbind, res, 
                          codeword = key$codewords, 
                          substrings = key$substrings))
res <- subset(res, StartingPosition != -1)

#  StartingPosition Occurences codeword substrings
#1                2          1        1    BCD|FGH
#2                3          1        2    CDE|EFG
#3                1          1        3    ABC|DEF    # 1. occurence of ABC
#4                4          1        3    ABC|DEF    
#5                7          1        3    ABC|DEF    # 2. occurence of ABC