在Python 3.3.2中计算短语频率

6

我一直在研究网上的不同资料,并尝试了各种方法,但只能找到如何计算唯一单词的频率而无法计算唯一短语。 我目前的代码如下:

import collections
import re
wanted = set(['inflation', 'gold', 'bank'])
cnt = collections.Counter()
words = re.findall('\w+', open('02.2003.BenBernanke.txt').read().lower())
for word in words:
    if word in wanted:
        cnt [word] += 1
print (cnt)

如果可能的话,我也想在这段文字中计算“央行”和“高通胀”这两个短语的使用次数。感谢您提供的任何建议或指导。

你想在文本中查找词二元组的频率吗? - jfs
@ J.F. Sebastian,某种程度上是这样,但是具体的,比如“高通货膨胀率”这样短语的频率。 - Raul
3个回答

2

首先,这是我生成 cnt 的方法(以减少内存开销):

def findWords(filepath):
  with open(filepath) as infile:
    for line in infile:
      words = re.findall('\w+', line.lower())
      yield from words

cnt = collections.Counter(findWords('02.2003.BenBernanke.txt'))

现在,关于短语的问题:
现在,让我们来谈谈关于短语的问题:
from itertools import tee
phrases = {'central bank', 'high inflation'}
fw1, fw2 = tee(findWords('02.2003.BenBernanke.txt'))   
next(fw2)
for w1,w2 in zip(fw1, fw2)):
  phrase = ' '.join([w1, w2])
  if phrase in phrases:
    cnt[phrase] += 1

希望这能有所帮助。

在Python 3.3中,您可以使用yield from - falsetru
phrase 变成 TrueFalse。因此,phrase in phrases 总是返回 False。 - falsetru
2
这段代码并不能产生OP想要的结果。请尝试使用the central bank high inflation作为文件内容,以及central bank high inflation。您可能需要使用类似于itertools.tee的东西。请参见itertools recipes中的pairwise配方。 - falsetru
@gnibbler: 你说得对!我怎么会错过那个呢?!现在已经修复了。 - inspectorG4dget
1
现在您正在对文件进行两次处理。让我编辑它以使用“tee”。 - John La Rooy
显示剩余8条评论

1

要在一个小文件中计算几个短语的文字出现次数:

with open("input_text.txt") as file:
    text = file.read()
n = text.count("high inflation rate")

有一个nltk.collocations模块,提供了识别经常连续出现的单词的工具:

import nltk
from nltk.tokenize import word_tokenize, sent_tokenize
from nltk.collocations import BigramCollocationFinder, TrigramCollocationFinder

# run nltk.download() if there are files missing
words = [word.casefold() for sentence in sent_tokenize(text)
         for word in word_tokenize(sentence)]
words_fd = nltk.FreqDist(words)
bigram_fd = nltk.FreqDist(nltk.bigrams(words))
finder = BigramCollocationFinder(word_fd, bigram_fd)
bigram_measures = nltk.collocations.BigramAssocMeasures()
print(finder.nbest(bigram_measures.pmi, 5))
print(finder.score_ngrams(bigram_measures.raw_freq))

# finder can be constructed from words directly
finder = TrigramCollocationFinder.from_words(words)
# filter words
finder.apply_word_filter(lambda w: w not in wanted)
# top n results
trigram_measures = nltk.collocations.TrigramAssocMeasures()
print(sorted(finder.nbest(trigram_measures.raw_freq, 2)))

0

假设文件不是很大-这是最简单的方法

for w1, w2 in zip(words, words[1:]):
    phrase = w1 + " " + w2
    if phrase in wanted:
        cnt[phrase] += 1
print(cnt)

嘿gnibbler,感谢你提供的所有有益见解!然而,当我将这段代码与上面的第一段代码合并时,它返回一个错误消息,指示“words”未被识别。你知道为什么吗?再次感谢你的帮助。 - Raul
words 只是你问题中的单词列表。for 循环将单词成对组合,以创建(两个单词的)短语。 - John La Rooy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接