如何使用python在文件中查找最常出现的单词对集合?

时间:2014-01-23 01:43:15

标签: python python-2.7 word-count

我的数据集如下:

"485","AlterNet","Statistics","Estimation","Narnia","Two and half men"
"717","I like Sheen", "Narnia", "Statistics", "Estimation"
"633","MachineLearning","AI","I like Cars, but I also like bikes"
"717","I like Sheen","MachineLearning", "regression", "AI"
"136","MachineLearning","AI","TopGear"

等等

我想找出最常出现的单词对,例如

(Statistics,Estimation:2)
(Statistics,Narnia:2)
(Narnia,Statistics)
(MachineLearning,AI:3)

这两个词可以是任何顺序,也可以是彼此之间的任何距离

有人可以在python中建议一个可能的解决方案吗?这是一个非常大的数据集。

非常感谢任何建议

所以这是我在@ 275365

的建议后尝试过的

@ 275365我尝试从文件中读取输入

以下内容
    def collect_pairs(file):
        pair_counter = Counter()
        for line in open(file):
            unique_tokens = sorted(set(line))  
            combos = combinations(unique_tokens, 2)
            pair_counter += Counter(combos)
            print pair_counter

    file = ('myfileComb.txt')
    p=collect_pairs(file)

文本文件与原始文件具有相同的行数,但在特定行中只有唯一的标记。我不知道我做错了什么,因为当我运行它时,它会将字母分成字母,而不是将输出作为单词的组合。当我运行此文件时,它会输出拆分字母而不是预期的单词组合。我不知道我在哪里弄错了。

2 个答案:

答案 0 :(得分:5)

您可能会从这样的事情开始,具体取决于您的语料库的大小:

>>> from itertools import combinations
>>> from collections import Counter

>>> def collect_pairs(lines):
    pair_counter = Counter()
    for line in lines:
        unique_tokens = sorted(set(line))  # exclude duplicates in same line and sort to ensure one word is always before other
        combos = combinations(unique_tokens, 2)
        pair_counter += Counter(combos)
    return pair_counter

结果:

>>> t2 = [['485', 'AlterNet', 'Statistics', 'Estimation', 'Narnia', 'Two and half men'], ['717', 'I like Sheen', 'Narnia', 'Statistics', 'Estimation'], ['633', 'MachineLearning', 'AI', 'I like Cars, but I also like bikes'], ['717', 'I like Sheen', 'MachineLearning', 'regression', 'AI'], ['136', 'MachineLearning', 'AI', 'TopGear']]
>>> pairs = collect_pairs(t2)
>>> pairs.most_common(3)
[(('MachineLearning', 'AI'), 3), (('717', 'I like Sheen'), 2), (('Statistics', 'Estimation'), 2)]

您想要这些组合中包含的数字吗?由于您没有具体提及将它们排除在外,我已将它们包括在内。

编辑:使用文件对象

您在上面第一次尝试时发布的功能非常接近工作。您唯一需要做的就是将每一行(这是一个字符串)更改为元组或列表。假设您的数据看起来与您在上面发布的数据完全一样(每个术语周围都有引号和逗号分隔术语),我建议您使用ast.literal_eval。 (否则,您可能需要使用某种正则表达式。)请参阅下面的ast.literal_eval修改版本:

from itertools import combinations
from collections import Counter
import ast

def collect_pairs(file_name):
    pair_counter = Counter()
    for line in open(file_name):  # these lines are each simply one long string; you need a list or tuple
        unique_tokens = sorted(set(ast.literal_eval(line)))  # eval will convert each line into a tuple before converting the tuple to a set
        combos = combinations(unique_tokens, 2)
        pair_counter += Counter(combos)
    return pair_counter  # return the actual Counter object

现在你可以像这样测试它:

file_name = 'myfileComb.txt'
p = collect_pairs(file_name)
print p.most_common(10)  # for example

答案 1 :(得分:0)

除了计算所有对之外,没有那么多你可以做的。

明显的优化是尽早删除重复的单词和同义词,执行词干(减少不同标记数量的任何东西都很好!),并且只计算(a,b)a<b(在你的例子中) ,只计算statistics,narnianarnia,statistics,但不能同时计算!)。

如果内存不足,请执行两次传递。在第一遍中,使用一个或多个散列函数来获得候选过滤器。在第二遍中,只计算通过此过滤器的单词(MinHash / LSH样式过滤)。

这是一个天真的并行问题,因此也很容易分发到多个线程或计算机。