Python:如何在文本中找到 n-gram 模式?

Posted

技术标签:

【中文标题】Python:如何在文本中找到 n-gram 模式?【英文标题】:Python: How to find n-gram patterns in the text? 【发布时间】:2012-03-06 08:57:12 【问题描述】:

我有一个可以任意长的字符串

s = 'Choose from millions of possibilities on Shaadi.com. Create your profile, search&contact; your special one.RegisterFree\xa0\xa0\xa0unsubscribing reply to this mail\xa0\n and 09times and this is limited time offer! and this is For free so you are saving cash'

我有一个垃圾邮件列表,可能像

p_words = ['cash', 'for free', 'limited time offer']

我只想知道输入文本中是否存在模式以及存在多少次?

只有一个字就变简单了

import re
p = re.compile(''.join[p_words])  # correct me if I am wrong here
m = p.match(s)  

但它可能是bi-gram, tri-gram or n-gram

我们如何处理这个问题?

【问题讨论】:

如果您需要不区分大小写的关键字搜索,请参阅my answer that shows the difference between full Unicode casefolding and mere .lower() method 【参考方案1】:
p = re.compile('|'.join(re.escape(w) for w in p_words))

p 将匹配p_words 中的任何字符串。

【讨论】:

没有理由不这样做。 @J.F.Sebastian 如果您将re.finditerre.findall 与生成的正则表达式一起使用。 @Amber: re.find* 枚举匹配项,但仍然自己不回答“多少次”。 @JFSebastian - 鉴于 OP 在不针对 ngram 时已经在使用正则表达式来解决他们的问题,因此假设他们能够根据需要实现计数部分似乎是合乎逻辑的。跨度> 【参考方案2】:

如果文字和字数不是很大可以从example开始:

d = w: s.count(w) for w in p_words if w in s
# -> 'cash': 1, 'limited time offer': 1

您可以将其性能与:

import re
from collections import Counter

p = re.compile('|'.join(map(re.escape, p_words)))
d = Counter(p.findall(s))
# -> Counter('limited time offer': 2, 'cash': 2)

将其速度与fgrep 进行比较以供参考。它应该能够快速匹配输入流中的多个字符串:

$ grep -F -o -f  patternlist.txt largetextfile.txt  | sort | uniq -c

输出

  2 cash
  2 limited time offer

【讨论】:

感谢@J.F.Sebastian 告诉我存在计数器,我不知道 @daydreamer:注意Counter 不是最快的,如果你使用这个算法:performance comparison【参考方案3】:

正则表达式使用“|”分隔器。将每种情况下的空格替换为 '\W+' 之类的东西,它匹配非字母,我认为你很高兴。

【讨论】:

以上是关于Python:如何在文本中找到 n-gram 模式?的主要内容,如果未能解决你的问题,请参考以下文章

来自python中的文本的n-gram

文本摘要:如何选择合适的 n-gram 大小

N-grams模型停顿词(stopwords)和标准化处理 - NLP学习

我需要啥算法来找到 n-gram?

算法:N-gram语法

如何使用 n-gram 进行分类任务?