NLTK中的FreqDist未排序输出
我刚开始学习Python,想自己研究语言处理。在Python中,有个叫NLTK的库,它有个功能叫FreqDist,可以告诉我文本中单词出现的频率,但不知为什么它没有正常工作。
这是教程让我写的代码:
fdist1 = FreqDist(text1)
vocabulary1 = fdist1.keys()
vocabulary1[:50]
简单来说,这段代码应该给我一个文本中出现频率最高的50个单词的列表。然而,当我运行这段代码时,得到的结果却是出现频率最低的50个单词,按照从最低到最高的顺序排列,和我预期的正好相反。我的输出结果如下:
[u'succour', u'four', u'woods', u'hanging', u'woody', u'conjure', u'looking', u'eligible', u'scold', u'unsuitableness', u'meadows', u'stipulate', u'leisurely', u'bringing', u'disturb', u'internally', u'hostess', u'mohrs', u'persisted', u'Does', u'succession', u'tired', u'cordially', u'pulse', u'elegant', u'second', u'sooth', u'shrugging', u'abundantly', u'errors', u'forgetting', u'contributed', u'fingers', u'increasing', u'exclamations', u'hero', u'leaning', u'Truth', u'here', u'china', u'hers', u'natured', u'substance', u'unwillingness...]
我完全按照教程来写的,但我一定是哪里出错了。
这是教程的链接:
http://www.nltk.org/book/ch01.html#sec-computing-with-language-texts-and-words
示例就在“图1.3:计算文本中出现的单词(频率分布)”这个标题下面。
有没有人知道我该怎么解决这个问题?
4 个回答
import nltk
fdist1 = nltk.FreqDist(text)
fdist1 里存放的是 'key' - 代表单词,'values' - 代表这些单词出现的频率。
上面的变量 fdist1 还没有排序,所以用这个命令时不会打印出前 50 个结果。请先使用下面的代码对它们进行排序:
sorted_fdist1 = sorted(fdist1 , key = fdist1.__getitem__, reverse = True)
sorted_fdist1[0:50]
这样就会打印出出现频率最高的 50 个单词。
作为使用 FreqDist 的另一种选择,你可以直接使用 `collections` 中的 Counter
,具体可以参考这个链接:https://stackoverflow.com/questions/22952069/how-to-get-the-rank-of-a-word-from-a-dictionary-with-word-frequencies-python/22953416#22953416 :
>>> from collections import Counter
>>> text = """foo foo bar bar foo bar hello bar hello world hello world hello world hello world hello world hello hello hello"""
>>> dictionary = Counter(text.split())
>>> dictionary
{"foo":3, "bar":4, "hello":9, "world":5}
>>> dictionary.most_common()
[('hello', 9), ('world', 5), ('bar', 4), ('foo', 3)]
>>> [i[0] for i in dictionary.most_common()]
['hello', 'world', 'bar', 'foo']
来自 NLTK的GitHub:
在NLTK3中,FreqDist是对collections.Counter的一个封装;Counter提供了一个叫
most_common()
的方法,可以按顺序返回项目。FreqDist.keys()
方法是标准库提供的,没有被重写。我觉得我们变得更加兼容标准库是件好事。谷歌代码上的文档非常旧,来自2011年。更新的文档可以在http://nltk.org网站找到。
所以在NLTK版本3中,不要使用fdist1.keys()[:50]
,而是用fdist1.most_common(50)
。
这个教程也已经更新了:
fdist1 = FreqDist(text1)
>>> print(fdist1)
<FreqDist with 19317 samples and 260819 outcomes>
>>> fdist1.most_common(50)
[(',', 18713), ('the', 13721), ('.', 6862), ('of', 6536), ('and', 6024),
('a', 4569), ('to', 4542), (';', 4072), ('in', 3916), ('that', 2982),
("'", 2684), ('-', 2552), ('his', 2459), ('it', 2209), ('I', 2124),
('s', 1739), ('is', 1695), ('he', 1661), ('with', 1659), ('was', 1632),
('as', 1620), ('"', 1478), ('all', 1462), ('for', 1414), ('this', 1280),
('!', 1269), ('at', 1231), ('by', 1137), ('but', 1113), ('not', 1103),
('--', 1070), ('him', 1058), ('from', 1052), ('be', 1030), ('on', 1005),
('so', 918), ('whale', 906), ('one', 889), ('you', 841), ('had', 767),
('have', 760), ('there', 715), ('But', 705), ('or', 697), ('were', 680),
('now', 646), ('which', 640), ('?', 637), ('me', 627), ('like', 624)]
>>> fdist1['whale']
906
这个回答有点旧了。请使用 这个回答。
为了排查这个问题,我建议你按照以下步骤操作:
1. 检查你使用的 nltk
版本:
>>> import nltk
>>> print nltk.__version__
2.0.4 # preferably 2.0 or higher
旧版本的 nltk
没有可以排序的 FreqDist.keys
方法。
2. 确保你没有不小心修改 text1
或 vocabulary1
:
打开一个新的命令行窗口,从头开始重新执行这个过程:
>>> from nltk.book import *
*** Introductory Examples for the NLTK Book ***
Loading text1, ..., text9 and sent1, ..., sent9
Type the name of the text or sentence to view it.
Type: 'texts()' or 'sents()' to list the materials.
text1: Moby Dick by Herman Melville 1851
text2: Sense and Sensibility by Jane Austen 1811
text3: The Book of Genesis
text4: Inaugural Address Corpus
text5: Chat Corpus
text6: Monty Python and the Holy Grail
text7: Wall Street Journal
text8: Personals Corpus
text9: The Man Who Was Thursday by G . K . Chesterton 1908
>>> from nltk import FreqDist
>>> fdist1 = FreqDist(text1)
>>> vocabulary1 = fdist1.keys()
>>> vocabulary1[:50]
[',', 'the', '.', 'of', 'and', 'a', 'to', ';', 'in', 'that', "'", '-', 'his', 'it', 'I', 's', 'is', 'he', 'with', 'was', 'as', '"', 'all', 'for', 'this', '!', 'at', 'by', 'but', 'not', '--', 'him', 'from', 'be', 'on', 'so', 'whale', 'one', 'you', 'had', 'have', 'there', 'But', 'or', 'were', 'now', 'which', '?', 'me', 'like']
注意,vocabulary1
中不应该包含字符串 u'succour'
(这是你原始帖子输出中的第一个unicode字符串):
>>> vocabulary1.count(u'succour') # vocabulary1 does **not** contain the string u'succour'
0
3. 如果你仍然遇到问题,检查你的源代码和文本列表,确保它们与下面的内容一致:
>>> import inspect
>>> print inspect.getsource(FreqDist.keys) # make sure your source code matches the source code below
def keys(self):
"""
Return the samples sorted in decreasing order of frequency.
:rtype: list(any)
"""
self._sort_keys_by_value()
return map(itemgetter(0), self._item_cache)
>>> print inspect.getsource(FreqDist._sort_keys_by_value) # and matches this source code
def _sort_keys_by_value(self):
if not self._item_cache:
self._item_cache = sorted(dict.items(self), key=lambda x:(-x[1], x[0])) # <= check this line especially
>>> text1[:40] # does the first part of your text list match this one?
['[', 'Moby', 'Dick', 'by', 'Herman', 'Melville', '1851', ']', 'ETYMOLOGY', '.', '(', 'Supplied', 'by', 'a', 'Late', 'Consumptive', 'Usher', 'to', 'a', 'Grammar', 'School', ')', 'The', 'pale', 'Usher', '--', 'threadbare', 'in', 'coat', ',', 'heart', ',', 'body', ',', 'and', 'brain', ';', 'I', 'see', 'him']
>>> text1[-40:] # and what about the end of your text list?
['second', 'day', ',', 'a', 'sail', 'drew', 'near', ',', 'nearer', ',', 'and', 'picked', 'me', 'up', 'at', 'last', '.', 'It', 'was', 'the', 'devious', '-', 'cruising', 'Rachel', ',', 'that', 'in', 'her', 'retracing', 'search', 'after', 'her', 'missing', 'children', ',', 'only', 'found', 'another', 'orphan', '.']
如果你的源代码或文本列表与上面的内容不完全一致,考虑重新安装 nltk
的最新稳定版本。