实现频繁词伪码

时间:2017-07-17 01:31:33

标签: python

我正在尝试实现频繁的单词伪代码。根据一个样本数据集,我应该返回2个频繁的单词,但我只返回第一个。 这是伪代码:

FrequentWords(Text, k)
    FrequentPatterns <-- an emty set
    for i <-- 0 to |Text| - k
        Pattern <-- the k-mer Text(i,k)
        Count(i) <-- PatternCount(Text,Pattern)
    maxCount <-- max value in array Count
    for i <-- 0 to |Text| - k
        if Count(i) = maxCount
        add Text(i,k) to FrequentPatterns
    remove duplicates from FrequentPatterns
    return FrequentPatterns

这是我的实施:

def PatternCount(Text, Pattern):
    Count = 0
    for i in range(0, (len(Text) - len(Pattern) + 1)):
        if Text[i:i+len(Pattern)] == Pattern:
           Count = Count + 1
    return Count

def FrequentWords(Text, k):
    FrequentPatterns = [0]
    Count = [0] * (len(Text) - k + 1)
    for i in range(0, (len(Text) - k + 1)):
        Pattern = Text[i:i+k]
        Count[i] = PatternCount(Text, Pattern)
    maxCount = max(Count)    
    for i in range(0, (len(Text) - k + 1)):        
        if Count[i] == maxCount:
            FrequentPatterns = Text[i:i + k] 
            return FrequentPatterns

以下是示例数据集: ACGTTGCATGTCGCATGATGCATGAGAGCT 4

我应该从代码返回: CATG GCAT

但我只是第一个 - CATG。请帮忙。

3 个答案:

答案 0 :(得分:1)

s = 'ACGTTGCATGTCGCATGATGCATGAGAGCT'
length = 4

我会用字典来累积结果。使用切片提取 next 字;在字典中为该单词的值添加一个;然后删除字符串中的第一个字符;循环,而字符串中有一个单词。

result = {}
while len(s) >= length:
    word = s[:length]
    result[word] = result.get(word, 0) + 1
    s = s[1:]

您可能可以使用collections.Counter or collections.defaultdict作为该位。如果单词不能重叠,请从字符串前面删除length个字符。保持过程简单会导致从循环底部的字符串中删除字符时效率低下。除非数据很长或者过程执行了很多次,否则它不重要。

然后找到具有最高频率

的单词
most = max(result.values())
frequent = []
for key, value in results:
    if value == most:
        frequent.append(key)

#frequent = [key for key, value in result.items() if value == most]

itertools recipe借用你可以创建一个产生所需长度的单词的迭代器

def n_wise(iterable, n=2):
    '''s -> (s0,s1), (s1,s2), (s2, s3), ... for n=2'''
    tees = itertools.tee(iterable, n)
    for i, thing in enumerate(tees, 1):
        for _ in range(i):
            next(thing, None)
    return zip(*tees)

程序的计数部分将变为

words = n_wise(s, length)
result = {}
for word in words:
    result[word] = result.get(word, 0) + 1

result中的密钥将是元组,例如('C', 'A', 'T', 'G')但可以使用''.join(('C', 'A', 'T', 'G'))重新构建它们。

答案 1 :(得分:1)

你应该考虑使用列表推导。

def pattern_count(text, pattern):
     matches = ([x for x in range(len(text) - len(pattern) + 1) if pattern in text[x:len(pattern) + x]])
     return len(matches)


def frequent_words(text, k):
    counts = [pattern_count(text, text[x:x + k]) for x in range(len(text) - k)]
    return set([text[x:x + k] for x in range(len(text) - k) if counts[x] == max(counts)])

pattern_count 将解析模式的字符串。我们拼接文本字符数组,因此我们可以检查该部分是否包含该模式。这允许我们在结果中包含重叠条目。例如,

pattern_count(ABABA,ABA) - &gt;结果是2,而不是1。

print(pattern_count("BABBASDCABCBABDDASDBBCASDBAB", "BAB"))
[0] 3

frequent_words 采用相同的文本,但不是模式,我们给它一个int,表示模式应该有多长。一旦我们得到满足我们的字符 k 要求的每个模式的出现次数列表,我们就会通过获取最频繁出现的条目来过滤它。最后,为了删除任何重复项,我们将列表转换为一个本身可以防止重复条目的哈希集,从而返回一个只有唯一值的集合。

测试:

print(frequent_words("BABBASDCABCBABDDASDBBCASDBAB", 3))
[0] {'BAB', 'ASD'}

希望这对你有用。

答案 2 :(得分:0)

改为使用dict

def FrequentWords(Text, k):
    FrequentPatterns = {}
    for i in range(0, (len(Text) - k + 1)):
        Pattern = Text[i:i+k]
        if Pattern in FrequentPatterns:
            FrequentPatterns[Pattern] += 1
        else:
            FrequentPatterns.update({Pattern: 1})
    for x in sorted(FrequentPatterns.items(), key=lambda m: m[1], reverse=True):
        print(x)