使用TF-IDF制作整个文档集的词云有不少人讲过,如何对文档集中的单篇文档制作TF-IDF词云,却很少人写过。参照别人的代码,自己花不少时间琢磨代码里的逻辑,改动后,终于能对文档集中的单篇文档制作TF-IDF词云了。
一、对文本进行分词、去标点,并将每篇文本分词后的结果存为一个列表元素,最终将整个文档集合表示成一个二维列表。
(1)导入Jieba分词工具
import os
import jieba
(2)文本路径
file_path = r'.\story' ## 故事文件路径
dictionary = r'.\专名汇总.txt' ##专名词表路径
stop_path = r'.\stopwords.txt' ##停用词文件路径
(3)定义需被去除的标点,及读入停用词
split_chars = " …《》,、。?!;:“”‘’'\n\r-=—()().【】"
with open(stop_path, 'r', encoding = 'utf-8-sig') as f:
stopwords = [s.strip() for s in f.readlines()]
(4)加载词典
jieba.load_userdict(dictionary)
(5)分词、去停用词,并将文档集合存为一个二维列表
storiesL = [] ##存储所有故事的列表
for i in range(1,41):
story_path = os.path.abspath(os.path.join(file_path, 'S' + str(i) + '.txt'))
with open(story_path, 'r', encoding = 'utf-8-sig') as f:
text = f.read()
text = text.replace('\n', ' ')
for char in split_chars:
text = text.replace(char, ' ')
seg_text = jieba.cut(text, cut_all = False)
tempL = [] #装故事文本去除了停用词的词序列
for word in seg_text:
word = word.strip()
if word not in stopwords:
tempL.append(word)
storiesL.append(' '.join(tempL)) ##词云
二、制作单个文本的TF-IDF词云
(1)导入相关模块
from sklearn import feature_extraction
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
from collections import defaultdict
#制作词云
from wordcloud import WordCloud, ImageColorGenerator
from PIL import Image
import matplotlib.pyplot as plt
(2)统计词袋中所有词的TF-IDF权重
tlist = storiesL
vectorizer=CountVectorizer()#该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在i类文本下的词频
transformer = TfidfTransformer(smooth_idf = False)#该类会统计每个词语的tf-idf权值
tfidf = transformer.fit_transform(vectorizer.fit_transform(tlist)) #第一个fit_transform是计算tf-idf,第二个fit_transform是将文本转为词频矩阵
word=vectorizer.get_feature_names()#获取词袋模型中的所有词语
weight=tfidf.toarray()#将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重 (矩阵的列维度表示词汇总数) document*word
(3)配置词云对象参数
font_path = 'msyh.ttc'
wc = WordCloud(font_path=font_path, # 设置字体
background_color="white", # 背景颜色
max_words=100, # 词云显示的最大词数
stopwords=stopwords,
max_font_size=100, # 字体最大值
width=1000, height=860, margin=2,# 设置图片默认的大小,但是如果使用背景图片的话,那么保存的图片大小将会按照其大小保存,margin为词语边缘距离
# prefer_horizontal=1,
)
(4)生成单个故事的TF-IDF词云
for i in range(40):
filename = str(i+1)+'.png'
tfidf_list = defaultdict(list)
tfidf_avg = {}
for j in range(len(word)):
tfidf_list[word[j]].append(weight[i][j])
for i,j in tfidf_list.items():
tfidf_avg[i] = sum(j)/len(j)
wc.generate_from_frequencies(tfidf_avg)
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
wc.to_file(filename)
本文的代码与其他对整个文本集生成TF-IDF词云的代码差异处就在这部分。对整个文本集生成TF-IDF在处理此部分的代码如下:
tfidf_list = defaultdict(list)
tfidf_avg = {}
for i in range(len(weight)):#打印每类文本的tf-idf词语权重,第一个for遍历所有文本,第二个for遍历某一类文本下的词语权重
for j in range(len(word)):
#获取每个词语对应的权重值
tfidf_list[word[j]].append(weight[i][j]) ## tfidef_list为 词:列表 构成的键值对,word为总词数,document为列表的长度,该列表记录某个词在每个文件中的词频
#对每个词语求权重值平均
for i,j in tfidf_list.items():
tfidf_avg[i] = sum(j)/len(j)
wc.generate_from_frequencies(tfidf_avg)
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
wc.to_file(filename)
可以发现,在本文中,求平均 tf-idf值 的代码和制作词云的代码都是放在第一个for循环中,而制作整个文本集的词云时,这些操作是放在for循环外。