Python - 比较多个文本文件中的n-gram

时间:2014-12-10 23:36:41

标签: python n-gram

第一次发布海报 - 我是一名新的Python用户,编程技巧有限。最后,我试图在同一目录中找到的众多文本文档中识别和比较n-gram。我的分析有点类似于抄袭检测 - 我想计算可以找到特定n-gram的文本文档的百分比。现在,我正在尝试更大问题的更简单版本,尝试比较两个文本文档中的n-gram。我没有问题确定n-gram,但我正在努力比较这两个文件。有没有办法将n-gram存储在列表中,以便有效地比较两个文档中存在的n-gram?这是我到目前为止所做的(原谅天真的编码)。作为参考,我提供下面的基本句子,而不是我在代码中实际阅读的文本文档。

import nltk
from nltk.util import ngrams

text1 = 'Hello my name is Jason'
text2 = 'My name is not Mike'

n = 3
trigrams1 = ngrams(text1.split(), n)
trigrams2 = ngrams(text2.split(), n)

print(trigrams1)
for grams in trigrams1:
    print(grams)

def compare(trigrams1, trigrams2):
    for grams1 in trigrams1:
        if each_gram in trigrams2:
            print (each_gram)
    return False 

感谢大家的帮助!

3 个答案:

答案 0 :(得分:0)

common功能中使用列表compare。将每个ngram附加到这两个三元组共有的列表中,最后将列表返回为:

>>> trigrams1 = ngrams(text1.lower().split(), n)  # use text1.lower() to ignore sentence case.
>>> trigrams2 = ngrams(text2.lower().split(), n)  # use text2.lower() to ignore sentence case.
>>> trigrams1
[('hello', 'my', 'name'), ('my', 'name', 'is'), ('name', 'is', 'jason')]
>>> trigrams2
[('my', 'name', 'is'), ('name', 'is', 'not'), ('is', 'not', 'mike')]
>>> def compare(trigrams1, trigrams2):
...    common=[]
...    for grams1 in trigrams1:
...       if grams1 in trigrams2:
...         common.append(grams1)
...    return common
... 
>>> compare(trigrams1, trigrams2)
[('my', 'name', 'is')]

答案 1 :(得分:0)

我认为连接ngrams中的元素并创建字符串列表然后进行比较可能更容易。

让我们用你提供的例子来讨论这个过程。

text1 = 'Hello my name is Jason'
text2 = 'My name is not Mike'

在应用nltk中的ngrams函数后,您将获得以下两个类似我的名称text1text2的列表:

text1 = [('Hello', 'my', 'name'), ('my', 'name', 'is'), ('name', 'is', 'Jason')]
text2 = [('My', 'name', 'is'), ('name', 'is', 'not'), ('is', 'not', 'Mike')]

如果你想比较ngrams,你应该小写所有元素,以免它被'my''My'计算为单独的标记,这是我们显然不想要的。

以下功能就是这样。

def append_elements(n_gram):
    for element in range(len(n_gram)):
            phrase = ''
            for sub_element in n_gram[element]:
                    phrase += sub_element+' '
            n_gram[element] = phrase.strip().lower()
    return n_gram

因此,如果我们提供text1,我们会得到['hello my name', 'my name is', 'name is jason'],这样更容易处理。

接下来我们制作compare函数。你是对的,我们可以假设我们可以使用一个列表来存储共性。我在这里命名为common

def compare(n_gram1, n_gram2):
    n_gram1 = append_elements(n_gram1)
    n_gram2 = append_elements(n_gram2)
    common = []
    for phrase in n_gram1:
        if phrase in n_gram2:
            common.append(phrase)
    if not common:
        return False
        # or you could print a message saying no commonality was found
    else:
        for i in common:
            print(i)

if not common表示common列表为空,在这种情况下,它会打印一条消息或返回False

现在,在您的示例中,当我们运行compare(text1, text2)时,唯一的共性是:

>>> 
my name is
>>>

这是正确的答案。

答案 2 :(得分:0)

当我遇到这个旧线程时,我正在执行与您非常相似的任务,该任务似乎工作得很好,但有一个错误。如果有人偶然发现此问题,我将在此处添加此答案。 ngrams中的nltk.util返回一个生成器对象,而不是一个列表。需要使用您编写的compare函数将其转换为列表。使用lower()进行不区分大小写的匹配。

完整示例:

import nltk
from nltk.util import ngrams

text1 = 'Hello my name is Jason'
text2 = 'My name is not Mike'

n = 3
trigrams1 = ngrams(text1.lower().split(), n)
trigrams2 = ngrams(text2.lower().split(), n)

def compare_ngrams(trigrams1, trigrams2):
    trigrams1 = list(trigrams1)
    trigrams2 = list(trigrams2)
    common=[]
    for gram in trigrams1:
        if gram in trigrams2:
            common.append(gram)
    return common

common = compare_ngrams(trigrams1, trigrams2)
print(common)

输出:

[('my', 'name', 'is')]