我有几个可变长度的字符串,例如:
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.代码字长度也可供我使用,所以无论代码字长度如何,我都希望能够做到这一点。
如果需要,请随时要求澄清!
由于
答案 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次。
步骤基本上是:
key$substrings
转换为正则表达式的可用模式
gregexpr
确定每个序列中每个子串模式的起始位置如果我们在字符串中有多个代码字出现,这将为您提供所有起始位置。例如:
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