下篇:python中文词频统计
python词频统计
这篇博客用来记录一下自己学习用python做词频统计的过程,分别用字典和第三方库来完成词频统计
一、用字典统计英文词频,所用文本《THE CATCHER IN THE RYE 》(麦田里的守望者)
链接:link
提取码:jz7p
涉及的第三方库及其在程序中的用途如下:
import string #去除英文标点符号
from nltk.corpus import stopwords #去掉一些停用词
这里说下停用词,所谓停用词,多是一些出现频繁但实际意义不大或是对文本分析帮助不大的词汇,如英文里的a,an,that 中文里的“的”、“是”等词,下面是一些语言的常用停用词库链接:[link](https://www.ranks.nl/stopwords)
第三方库的使用将使我们的词频统计工作变得更为简单且细致,在接下来的用到时再细说。现在,让我们捋一捋词频统计的流程,显然,我们首先要拿到文本资源,并将需要处理的字符从文本中读出来:
f = open('E:\Python_code\Big_data\homework4\maitian.txt')
text = f.read()
f.close() #用open()打开的文件记得要关闭
#或者用下面这种方式,python会自动帮我们关闭文件
with open('E:\Python_code\Big_data\homework4\maitian.txt') as f:
text= f.read()
接着,我们需要对得到的text字符串做一些处理,当然我们也可以简单粗暴地直接用split()函数对text进行切分,但是这样文本中的标点符号及单词的大小写问题就没有得到处理,影响统计结果。string.punctuation包含了要去除的英文符号,这是第三方库的便捷点,让我们不必手动将一个个标点打出来
stop_words = stopwords.words('english') #要去掉的停用词
ls = list(string.punctuation) #要去除的英文标点符号,包含!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
text = text.lower() #统一为小写格式
for i in ls: #将标点符号替换为空格
text = text.replace(i," ")
lis = text.split() #切分单词
split()函数定义如下,sep参数是分隔符,默认对空格符,回车符,换行符等空格进行切分,maxsplit参数是最大切分次数,一般不需要指定,函数返回一个切分后的字符串列表
def split(self, sep: str , maxsplit: SupportsIndex = …)
这样,我们就得到了切分后的单词列表,可以用切片的方法看一下里面的单词 print(lis[:20])
[‘the’, ‘catcher’, ‘in’, ‘the’, ‘rye’, ‘by’, ‘j’, ‘d’, ‘salinger’, ‘to’, ‘my’, ‘mother’, ‘1’, ‘if’, ‘you’, ‘really’, ‘want’, ‘to’, ‘hear’, ‘about’]
可以看到,列表中还有单个的字母和数字以及一些停用词,这对我们的词频统计工作是不利的,应该想办法去掉,当然,处理方式是多种多样的,我这里就简单粗暴一点,把长度为1的字符都去掉,咋看这步似乎包括了去标点符号。但如果你不想去掉所有长度为1的字符,那么单独去掉标点符号还是有必要的。
counts= {}
for i in lis: #统计词频 ,不统计长度为1的词
if(len(i) >1):
counts[i] = counts.get(i,0)+1
for word in stop_words: #去掉停用词
counts.pop(word,0)
简单介绍下字典的两个方法,get()方法用来找与键(key)对应的值的,找到了就返回对应的值,没找到就返回默认值(default), pop()方法用来移除字典中某一键值对,如果有与(key)对应的值就将键值对移除并返回键对应的值(value),没有就返回默认值(default)
get(self, key , default )
pop(self, key, default)
这样,我们就得到了一个词频字典,可以直接打印看里面的内容,但是内容太多,并不建议这么做,我们对其按值(也就是单词出现的频数)进行排序,将结果赋给一个列表,然后看一下列表中的前20个元素:
这里简单介绍一下sorted函数,这是一个python内置函数,
sorted(iterable, cmp=None, key=None, reverse=False)
iterable – 可迭代对象。
cmp – 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0,一般不要指定。
key --指定排序依据,下面的用法就是按照传入元组对的第二个值进行排序(按频数排序)key.items()返回键值组成的元组对,lambda函数则取传入元组对的第二个值作为返回值。
reverse – 指定排序规则,为时True 降序排列, False 升序(默认)。
ls1 = sorted(counts.items(),key=lambda x:x[1],reverse=True)
print(ls1[:20])
[(‘said’, 705), (‘like’, 403), (‘old’, 397), (‘know’, 316), (‘one’, 281), (‘get’, 261), (‘got’, 257), (‘goddam’, 245), (‘go’, 245), (‘right’, 244), (‘around’, 238), (‘even’, 238), (‘hell’, 234), (‘really’, 228), (‘something’, 220), (‘could’, 208), (‘anything’, 205), (‘though’, 191), (‘mean’, 183), (‘time’, 183)]
另外,还可以对排序结果做些改进,如将上面的"get"和"got"当成一个词处理等
下面贴一份完整代码
import string
from nltk.corpus import stopwords
f = open('E:\Python_code\Big_data\homework4\maitian.txt')
text = f.read()
f.close()
stop_words = stopwords.words('english') #要去掉的停用词
ls = list(string.punctuation) #要去除的英文标点符号
text = text.lower() #统一为小写格式
for i in ls: #将标点符号替换为空格
text = text.replace(i," ")
lis = text.split()
counts= {}
for i in lis: #统计词频 ,不统计长度为1的词
if(len(i) >1):
counts[i] = counts.get(i,0)+1
for word in stop_words: #去掉停用词
counts.pop(word,0)
ls1 = sorted(counts.items(),key=lambda x:x[1],reverse=True) #词频排序
print(ls1[:20])
二、用collections.Counter()统计词频
接下来介绍使用第三方库完成词频统计的方法,整体的逻辑其实和上面差不多,只是使用了第三方库而已,这样做的好处是可以减少代码量,提高程序运行效率,另外有许多第三方库都可以实现词频统计功能,这里仅介绍比较常见的两种
import collections
import string
from nltk.corpus import stopwords
f = open('E:\Python_code\Big_data\homework4\maitian.txt')
text = f.read()
f.close()
stop_words = stopwords.words('english') #要去掉的停用词
ls = list(string.punctuation) #要去除的英文标点符号
text = text.lower() #统一为小写格式
for i in ls: #将标点符号替换为空格
text = text.replace(i," ")
lis = text.split()
cl = collections.Counter(lis)#词频统计
for i in stop_words: #去掉停用词
cl.pop(i,0)
print(cl.most_common(20))
三、用pandas库统计词频
import pandas as pd
import string
from nltk.corpus import stopwords
f = open('E:\Python_code\Big_data\homework4\maitian.txt')
text = f.read()
f.close()
stop_words = stopwords.words('english') #要去掉的停用词
ls = list(string.punctuation) #要去除的英文标点符号
text = text.lower() #统一为小写格式
for i in ls: #将标点符号替换为空格
text = text.replace(i," ")
lis = text.split()
ds = pd.Series(lis).value_counts()
for i in stop_words:
try: #处理找不到元素i时pop()方法可能出现的错误
ds.pop(i)
except:
continue #没有i这个词,跳过本次,继续下一个词
print(ds[:20])
贴个测试图: