序列文件中最常见的子串的顶部

时间:2014-03-11 18:11:01

标签: python r

我有一个包含许多序列的文件(所有序列都有不同的长度),如下所示:

5-2-6
5-6-6-6-1-8
4
1-7-6-6-2-6-6-1
18-24-2-6-6-1-8

我需要计算所有序列中最频繁的子串并得到如下结果:

6-6       5 times
2-6       3 times
6-6-1     3 times
6-1       3 times
6-1-8     2 times
1-8       2 times
2-6-6-1   2 times
2-6-6     2 times

子字符串可以是从2个数字开始的任何长度。我应该在代码中提供更改子字符串长度的机会,例如,查找超过3个数字的子字符串。

我知道我应该使用后缀树,但我找不到适合我案例的例子((

语言:R或Python。

2 个答案:

答案 0 :(得分:1)

你不需要后缀树;只需拆分序列并使用sliding window iterator来生成子串;循环以最小大小开始循环到行上的数字将允许您生成不同大小的子串。

然后collections.Counter() object可以跟踪计数:

from collections import Counter
from itertools import islice

def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result    
    for elem in it:
        result = result[1:] + (elem,)
        yield result

minimum_size = 2
counts = Counter()

with open(filename) as infh:
    for line in infh:
        parts = line.strip().split('-')
        # count substrings of various sizes
        counts.update('-'.join(sp) 
                      for size in range(minimum_size, len(parts) + 1)
                      for sp in window(parts, size))

然后Counter.most_common() method会为您提供按频率排序的排序列表子字符串:

for substring, count in counts.most_common():
    print '{:<20} {:>3d} times'.format(substring, count)

对于您的样本数据,前10个条目是:

6-6                    5 times
6-6-1                  3 times
2-6                    3 times
6-1                    3 times
2-6-6                  2 times
1-8                    2 times
6-1-8                  2 times
6-6-1-8                2 times
2-6-6-1                2 times
18-24-2-6-6            1 times

如果您想关注不同的最小子字符串长度,则不必重新计算整个文件。您可以改为过滤Counter对象;计算键中的-个字符:

for substr, freq in counts.most_common():
    if substr.count('-') < 2:
        # skip substrings shorter than 3 elements
        continue

答案 1 :(得分:1)

R不是最好的语言,因为树(据我所知)并没有很好地实现。如果你正在寻找一个快速而肮脏的解决方案,这将是有效的。它无论如何都没有效率:

# Create some data
set.seed(1)
data<-replicate(1000,sample(1:10,round(runif(1,1,8)),replace=TRUE))
# A function for all substrings
all.substrings<-function(s) unlist(sapply(1:length(s), function(y) sapply(y:length(s), function(x) s[y:x])),recursive=FALSE)
# Grab all strings
substrings<-unlist(sapply(data,all.substrings),recursive=FALSE)
# Strip one length substrings
substrings<-substrings[lapply(substrings,length)>1]
# Paste them together so you can easily aggregate
substrings.pasted<-sapply(substrings,paste,collapse=' ')
# Aggregate and sort.
sorted.results<-sort(table(substrings.pasted),decreasing=TRUE)
# Display
head(sorted.results)
# 10 3 4 10  8 1  9 4  9 2 8 10 
#   52   50   48   48   47   45 

所以序列10 3存在52次,即最大值。