首页 > 解决方案 > 在 Python 中按 ID 有效地计算 ngram

问题描述

我有一个包含 10,000 个 ngram(超过 1 个单词的短语)和 650 万条包含不同数量文本(从 10 个字符到 5,000 个字符)的记录的列表。我希望在我的数据框中创建 10,000 个新列,每个列都包含相关 ngram 的计数。我当前的解决方案包括使用文本循环遍历数据框中的列,使用 re.findall 计算 ngram 在每一行中出现的次数,将 findall 方法的长度放在一个列表中,然后使用该列表创建数据框中的新列。

由于内存限制,我一次对数据 100,000(6.5M)行进行分页。浏览一个页面大约需要五个小时,其中最终结果是一个数据框,其中包含原始列和 10,000 列(每个 ngram 列)。因为我有 65 页要读完,所以我预计需要 325 小时才能读完所有这些。

有一个更好的方法吗?我试图找到一种 numpy 矢量化方法,但结果是空的。

编辑:在处理了更多之后,我开始使用 Pandas 矢量化

ngram = 'hello world'
df["columnCnt"] = df["text_column"].str.count(ngram)

我正在遍历 10,000 个 ngram 的列表,并为 10,000 个中的每一个调用 str.count。有没有办法对它进行矢量化,以便所有 10,000 个都比循环更快地完成?

标签: pythonpandas

解决方案


例如,这将计算短语中的所有 1、2、3 克:

from collections import defaultdict
phrase='worms in the belly of the leviathan. we the living bear the cross of history when in the company of dogs it behooves one to act like a dog'

allwords = phrase.split()
ngram_dict = defaultdict(int)
for n in [1,2,3]:
 for i in range(len(allwords)-n):
     words=' '.join([allwords[i+j] for j in range(n)])
     ngram_dict[words]+=1

然后找到您的列表与上面的 ngram 的交集。

ngrams_to_detect=['worms','dogs','worms in','act like','monster trucks']
detected=set(ngram_dict.keys())
relevant_detected = detected.intersection(ngrams_to_detect)
Out[92]: {'act like', 'dogs', 'worms', 'worms in', 'the'}

not_found = set(ngrams_to_detect)-relevant_detected
Out[93]: {'monster trucks'}

这里有一些权衡你的列表有多完整,以及在生成不相关的 ngram 之上浪费了多少时间。可以通过以下方式返回计数:

detected_counts = {k:v for k,v in ngram_dict.items() if k in relevant_detected}
Out[100]: {'worms': 1, 'dogs': 1, 'worms in': 1, 'act like': 1, 'the': 5}

推荐阅读