在文本处理中,我们经常需要对文本中的单词出现频率做一个统计,本文以英文小说《瓦尔登湖》为例,统计一下作者最喜欢用什么单词,他们各自的出现频率如何。
首先需要《瓦尔登湖》的文本:点击下载《瓦尔登湖》(https://pan.baidu.com/s/1o75GKZ4)
思路分析:
- 首先,要打开文件,把里面的内容写到字符串里面。
- 接着,要对字符串进行分词,分割成独立的单词。
- 最后,根据每个单词进行词频统计。
把下载好的“Walden.txt”放到桌面,复制一下完整的路径名,特别注意:
Windows系统下,默认的文件名路径子级和父级之间可能是用反斜杠“ \ ”表示的,而在Python中,子级和父级之间用正斜杠“ / ”表示。
文件打开的时候,如果出现以下错误:
UnicodeDecodeError: 'gbk' codec can't decode byte 0xbf in position 2: illegal multibyte sequence
说明文件编码格式异常,解决办法:在文件打开的语句中添加 encoding = ' utf-8 ',注意添加在open( )函数的最后。
with open(path,'r') as text:
# 添加utf-8编码支持,原语句改为:
with open(path,'r',encoding='utf-8') as text:
使用stringlist.split()函数进行分词,使用stringlist.count()函数进行统计词频
代码如下:
path = 'C:/Users/xiaokai/Desktop/Walden.txt'
with open(path,'r',encoding='utf-8') as text: # 读入文本
words = text.read().split() # 开始分词
print(words)
for word in words:
print('{}--{} times'.format(word,words.count(word))) # 把单词和词频分别打印出来
运行结果
tried.--1 times
Whatever--4 times
have--660 times
been--167 times
thy--23 times
failures--3 times
hitherto,--1 times
"be--1 times
分析问题:
发现输出有点怪异,出现了 “tried. ”,“hitherto,” 这样的单词,还有更多的问题:
- 单词前后跟了“,”,“.”,“?”等各种各样的符号。
- 有许多单词被重复统计了。
- 有一些单词,例如‘“Some”和“some”是同一个单词,但是因为“Some”首字母大写也被认为是两个单词。
因此作出更多的改进:
- 去掉首尾连在一起的字符串,并且全部转换成小写字母。
- 创建一个单词集合,集合的性质保证了不会出现重复的单词,确保不会出现重复统计单词的现象。
- 创建一个字典,key为文本里出现的单词,value为单词在文本中出现的频率。
- 在字典中,根据词频顺序打印键值对。
改进之后的代码如下:
import string
with open(path,'r',encoding='utf-8') as text:
# 1. 首先进行分词
raw_words = text.read().split()
# 2. 把每个单词首尾连在一起的符号去掉,大写字母统一成小写
words_list = [word.strip(string.punctuation).lower() for word in raw_words]
# 3. 数据结构转换成集合,这里重复的单词会被自动丢弃
words_set = set(words_list)
# 4. 创建字典键值对:key为单词,value为单词出现的频率
# 冒号左边为单词,冒号右边为词频
words_dict = {keyword:words_list.count(keyword) for keyword in words_set}
# 5. 根据words_dict中value的值对字典进行排序输出
# 这里采用了lambda表达式,lambda word: word[1]表示输入一个word词条,返回word[1](词频)
# word是一个词条,word[0]是单词,word[1]是单词出现的频率
for word in sorted(words_dict.items(), key = lambda word: word[1], reverse = True):
print('{}--{} times'.format(word[0],word[1]))
代码解释:
- strip()函数的作用是去除单词首尾的符号,其中string.punctuation就是一个字符集,包含!@#¥%&*等符号,使用strip(string.punctuation)可以去除首尾的这些符号。
- word.lower()函数把字母全部转换成小写。
- sorted()函数对字典进行排序,默认对key进行排序,但这里对value进行排序,所以这里使用lambda表达式,在key = lambda word: word[1]中,返回值是word[1],也就是words_dict中的value。
参考博客:
Python strip()方法 | 菜鸟教程
http://www.runoob.com/python/att-string-strip.html
python字典按照value进行排序 - ketchup_酱 - 博客园
https://www.cnblogs.com/timtike/p/6562402.html