我想使用 python 计算文件中所有二元组(相邻单词对)的出现次数。在这里,我正在处理非常大的文件,所以我正在寻找一种有效的方法。我尝试在文件内容上使用带有正则表达式“\w+\s\w+”的计数方法,但事实证明它并不有效。
给定包含术语的列表列表,返回最常见的 二元组。返回值应该是形式为 (bigram, count),按降序排列,仅限于前 n 个二元组。在示例中 下面提供了两个文件;最上面的两个二元组是 'b c' (3 出现)和“a b”(出现 2 次)。 这是我尝试过的,但它列出了所有二元组的计数..
from itertools import tee, islice
def find_top_bigrams(terms,n):
tlst = terms
while True:
a, b = tee(tlst)
l = tuple(islice(a, n))
if len(l) == n:
yield l
next(b)
tlst = b
else:
break
find_top_bigrams([['a', 'b', 'c', 'd'], ['b', 'c', 'a', 'b', 'c']], 2)
>>[('b c', 3), ('a b', 2)]
我希望 find_top_bigrams 函数列出最多两个输出事件。
最佳答案
如果数据适合内存,collections.Counter
就是你的 friend 。
import collections
def list_to_bigrams(somelist):
it = iter(somelist)
old = next(it, None)
for new in it:
yield old, new
old = new
def find_top_bigrams(n, *manylists):
c = collections.Counter()
for somelist in manylists:
c.update(list_to_bigrams(somelist))
return c.most_common(n)
如果数据太大而无法放入内存,那么您将不得不在磁盘上工作 - 速度要慢得多,但是,对于数十 GB 或更多,您还要做什么?对于这种“大数据”情况,有一些可用的策略 - 一直到复杂的分布式方法(例如 MapReduce),到基于合并和排序普通磁盘文件的简单单处理器方法。
如果您能更好地解释您的运营参数,我可以详细介绍适当的策略。但从你的例子来看,“非常大的文件”对你来说可能并不像对我来说意味着一样(几十或几百千兆字节是中等大小——使用“大”这个词需要太字节,等等比“非常大”)。
因此,使用我上面提供的代码,调用会略有不同:
find_top_bigrams(2, ['a', 'b', 'c', 'd'], ['b', 'c', 'a', 'b', 'c'])
[(('b', 'c'), 3), (('a', 'b'), 2)]
首先是数字 2,因此所有其余参数可以分别是一个列表(而不是必须使用不太优雅的列表列表)。但是,如果必须的话,切换参数当然是微不足道的——只需将 def
语句更改为
def find_top_bigrams(manylists, n):
您可以完全使用示例中给出的调用语法,而我上面建议的其余代码保持不变。
补充:特别的是,输出似乎被限制为字符串而不是元组 - 微不足道的更改(尽管严重浪费了良好的 CPU 周期),只需更改
yield old, new
至
yield old + ' ' + new
或选择的其他格式化操作(但这是最简单的)。当然,通过这个微小的更改,结果将变为 [('b c', 3), ('a b', 2)]
。
关于python - 使用 python 的二元组函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28270718/