python实现英文词频统计【记录】
前言
之前遇到一篇很长很长的文档,需要统计一下某一个人物或者某一些词出现的次数,这种情况人力自然是不行。但是可以利用 python 来解决这个问题。例如:我们可以利用 python 统计出《哈姆雷特》或者是《红楼梦》中人物出场的频率。
这篇文章特此用来记录一下,防止自己遗忘。
首先用《哈姆雷特》试一下:
第一步:下载《哈姆雷特》英文版 TXT 文件
第二步:开始编写代码
txt = open("hamlet.txt", "r").read() # 打开文件 r 读权限
1.对打开后的文件进行预处理
for ch in '# $ % & () * + , - . : ; < = > ? @ [\\] ^ {}':
txt = txt.replace(ch, "") # 文中的特殊字符用空格代替
2.文本分词
txt = txt.lower() # 将所有的字母转化为小写
words = txt.split() # 什么都不填表示用空格来分隔
这是英文文本,单词之间本身就存在空格符,所以是不需要分词的。这一步应该算是文本预处理。但是中文文本词与词之间没有空格符,所以需要使用中文分词工具,例如如下的第三方库:jieba、pkuseg、pynlpir、thulac 等等。
3.词频统计
这就有一个问题,这些词我们预处理已经完成,但是它们应该去哪里呢?
所以我们需要一个存放词的容器——没错,就是字典。因为我们要统计的结果是词+它出现的次数,所以可以看作是字典中键与值之间的关系。
所以,先定义一个存放词的空字典:
counts = {}
然后我们需要把预处理过的词都放入空字典。然后计算就可以了。
if word in counts:
counts[word] = counts[word] + 1
else:
counts[word] = 1
这样我们就能计算出词出现的次数了,但是这样不够简洁,我们还可以这样写:
for word in words:
counts[word] = counts.get(word,0) +1
第二行中的 count[word]是把遍历到的词作为 key,后面的表达式,get 方法去查询 key 出现的次数,出现一次,就+1,如果没有,返回 0。这样,就可以了。
另外,词频统计会统计所有的词出现的次数,但是,我们有时候做分析或者是其他需要的结果中并不需要这么多的词,所以我们可以进一步完善一下代码。
excludes = {"the", "and", "of", "you", "a", "i", "my", "in"}
for word in excludes:
del(counts[word])
这样,我们就把一些冠词、连接词、介词一些我们不太需要的词都排除掉。依然是利用 for 循环去遍历文件中的词,并用 del 方法删去它们。
【上面的排词库可以随着程序的运行一步一步添加词汇,以达到打印对自己有意义的结果的目的】
至此,其实单单是统计词频的工作已经做完了,但是,我们得拿到这个结果,所以,我们定义一个空列表来存储它们。
items = list(counts.items())
print(items)
打印出来的结果会是这样:[('tragedy', 3), ...],列表中包含的是字典中所有键值对形成的元组。
emm…但是这个结果依然有点不尽人意。原因是这个结果是把字典中的键值形成的元组,保存到列表里面去,但是字典是无序的,打印出来的结果就仅仅只是一个结果,我们无法统计那个词频率最高,那个最低,当然,数据少了还可以,如果数据一多,拥有庞大数据的列表我们就无从下手了,所以,我们得实现排序。
4.结果排序(这里要用到 sort()和 lambda 函数)
items.sort(key=lambda x: x[1], reverse=True)
这样,就实现了以词出现的次数为条件的降序排序。sort()方法便是以第一列为基准升序排序的。但是我们用 lambda 这个匿名函数就可以了让它以第二列为基准降序排序。
5.输出排序后的结果
因为结果很多,尤其是大文件,我们会得到一个信息量很大的结果,不过呢,我们可以根据自己的需要打印排名前 10 或者前 20 的结果。
for i in range(10):
word, count = items[i]
print("{0:<10}{1:>5}".format(word, count))
源代码:
txt = open("hamlet.txt", "r").read() # 打开文件 r 读权限
for ch in '# $ % & () * + , - . : ; < = > ? @ [\\] ^ {}':
txt = txt.replace(ch, "") # 文中的特殊字符用空格代替
txt = txt.lower() # 将所有的字母转化为小写
words = txt.split() # 什么都不填表示用空格来分隔
counts = {}
for word in words:
counts[word] = counts.get(word,0) +1