# Zipf定律指出,文本中标识符出现的频率与其在排序列表中的排名或位置成反比。
# 所以,频率最高的单词出现的频率大约是出现频率第二位的单词的2倍,而出现频率第二位的单词则是出现频率第四位的单词的2倍。
# 该定律描述了标识符在语言中是如何分布的:一些标识符非常频率的出现,另一些出现频率较低,还有一些基本上不出现。
# 使用NLTK获取Zipf定律的双对数图
# 单词在文档中的排名相对其出现的频率的对对数图
# 注意:原书使用的字典没有排序
def main():
import nltk
from nltk.corpus import gutenberg
from nltk.probability import FreqDist
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')
# 建立一个字典统计词频
fd = FreqDist()
# 遍历每片文章
for text in gutenberg.fileids():
# 每篇文章的每个单词
for word in gutenberg.words(text):
# value + 1
fd[word] += 1
# 查看前五个
print(list(fd.items())[:5])
# 排序输出频率最高的看一下
fd_sorted = sorted(fd.items(), key = lambda x: x[1], reverse = True)
# print(fd_sorted[:5])
fd_sorted_dict = dict(fd_sorted)
# 排名列表
ranks = []
# 频率列表
freqs = []
for rank, word in enumerate(fd_sorted_dict):
ranks.append(rank + 1)
freqs.append(fd_sorted_dict[word])
# 绘图
plt.loglog(ranks, freqs)
# 横坐标
plt.xlabel('frequency(f)', fontsize=14, fontweight='bold')
# 纵坐标
plt.ylabel('rank(r)', fontsize=14, fontweight='bold')
plt.grid(True)
plt.show()
main()
# 执行结果
[('[', 115), ('Emma', 866), ('by', 8012), ('Jane', 303), ('Austen', 3)]
[(',', 186091), ('the', 125748), ('and', 78846), ('.', 73746), ('of', 70078)]
![](https://i-blog.csdnimg.cn/blog_migrate/f52cd560fbf580b403408f75558582ae.png)