python使用tkinter库实现自定义的词云图和top10词频统计

Ingrid ·
更新时间:2024-09-20
· 536 次阅读

这是介绍tkinter库实现桌面应用程序开发的第三篇博文,坚持不易,且行且珍惜。希望我的分享,能帮助大家少走弯路,提高学习效率。

这篇博文,我打算和大家分享一下当前比较火的额词云效果以及实现top10的统计功能,通过良好的、友善的可视化界面能提高感知和实用度,因此我这里继续使用tkinter库作为前端的展示开发库,在这里,我将使用ttk的Progressbar实现在统计过程中的等待交互窗口、使用notebook进行分TAB页显示,使用treeview实现词频统计的列表展现,然后使用LABEL加载词云图,也使用toplevel实现子窗口展现。因此,这篇博文还是非常值得大家花点时间参观一下的。

整体内容大致包括:

1、使用jieba库进行中文分词和词频统计

2、使用wordcloud库生成词云

3、使用tkinter库进行可视化展现

4、使用多线程技术进行异步监听加载

一、jieba库介绍

Jieba是python比较好用的分词模块,可用于中文句子/词性分割、词性标注、未登录词识别,支持用户词典等功能。能较好实现中文分词,同时支持繁体分词。

jieba.cut()提供了三种分词模式,具体包括如下:

精确模式:试图将句子最精确地切开,适合文本分析;

全模式:把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义,存在过度切分的问题;

搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。

举例如下:

import jieba import re # 正则表达式库 text = "Jieba是python比较好用的分词模块,可用于中文句子/词性分割、词性标注、未登录词识别,支持用户词典等功能。能较好实现中文分词,同时支持繁体分词。" # 文本预处理 # 定义正则表达式匹配模式,将符合模式的字符去除 pattern = re.compile(u'\t|\n|\.|-|:|;|\)|\(|\?|"|、|,|。|/') text = re.sub(pattern, '', text) #全模式 seg_list = jieba.cut(text, cut_all = True) print( "全模式:\n" + '/' .join(seg_list)) # 精确模式 seg_list = jieba.cut(text, cut_all = False) print('精确模式:\n' + '/' .join(seg_list)) # 搜索引擎模式 seg_list = jieba.cut_for_search(text) print('搜索引擎模式:\n' + '/'.join(seg_list))

运行结果如下:

全模式: Jieba/是/python/比较/好/用/的/分词/模块/可用/用于/中文/文句/句子/词性/分割/词性/标注/未/登录/词/识别/别支/支持/用户/词典/等/功能/能/较/好/实现/中文/分词/同时/支持/繁体/分词 精确模式: Jieba/是/python/比较/好用/的/分词/模块/可/用于/中文/句子/词性/分割/词性/标注/未/登录/词/识别/支持/用户/词典/等/功能/能/较/好/实现/中文/分词/同时/支持/繁体/分词 搜索引擎模式: Jieba/是/python/比较/好用/的/分词/模块/可/用于/中文/句子/词性/分割/词性/标注/未/登录/词/识别/支持/用户/词典/等/功能/能/较/好/实现/中文/分词/同时/支持/繁体/分词

大家可以根据具体实际的需要进行自行选择使用哪种模式。

实现词频统计的具体脚本如下:

import jieba import collections import re # 正则表达式库 fn = open('zyds.txt', encoding="utf-8") # 打开文件 text = fn.read() # 读出整个文件 print(text) fn.close() # 关闭文件 # 文本预处理 # 定义正则表达式匹配模式,将符合模式的字符去除 pattern = re.compile(u'\t|\n|\.|-|:|;|\)|\(|\?|"|、|,|。| |”|“|;') text = re.sub(pattern, '', text) #进行词频统计 text_list = jieba.cut(text, cut_all=False) # 词频TOP10高频统计 word_counts = collections.Counter(text_list) # 对分词做词频统计 word_counts_top10 = word_counts.most_common(10) # 获取前10最高频的词 print (word_counts_top10) # 输出检查

备注:其中文件名可以根据自己实际文件路径和名称进行修改。

在上述脚本的输出结果中,也许大家会发现有很多语气词、或者非关键词被提取出来,因此在这个环节我们可以通过设置stop_words进行关键词过滤和优化。实现逻辑为:新定义一个列表,然后进行过滤,过滤完毕之后的词append到新的列表中去。相关脚本如下:

定义去除词典 stop_words = [u'的', u',',u'和', u'是', u'随着', u'对于',u'对',u'等',u'能',u'都',u'。', u' ',u'、',u'中',u'在',u'了',u'通常',u'如果',u'我们',u'需要'] # 自定义去除词库 new_text_list=[] for word in text_list: # 循环读出每个分词 if word not in stop_words: # 如果不在去除词库中 new_text_list.append(word) # 分词追加到列表

二、使用wordcloud库生成词云图

wordcloud库通常和jieba结合使用,将分好的单词以图片的方式展示出来,根据单词出现的次数使单词突出。

wordcloud库是python非常优秀的词云展示第三方库。词云以词语为基本单位更加直观和艺术的展示文本, wordcloud把词云当作一个对象,它可以将文本中词语出现的频率作为一个参数绘制词云,而词云的大小、颜色、形状等都是可以设定的。

from wordcloud import WordCloud from PIL import Image # 图像处理库 import numpy as np # numpy数据处理库 mask = np.array(Image.open('timg1.jpg')) # 定义词频背景 # mask = ImageColorGenerator(back_img) w_cloud = WordCloud( font_path="c:\windows\Fonts\simhei.ttf", background_color='white', width=1000, height=600, mask=mask).generate_from_frequencies(text_list) # 输出成图片: w_cloud.to_file('wordcloud.jpg')

图片输出结果如下:

这里简要讲下几个会影响图像清晰问题的WordCloud的参数:

mask:遮罩图,字的大小布局和颜色都会依据遮罩图生成。

background_color:背景色,默认黑。根据说明文档,如果想设置透明底色的云词图,那么可以设置background_color=None, mode="RGBA" 生成云词图。

max_font_size:最大字号。

min_font_size:最小字号。不设置的情况下,默认是4。

scale:根据说明文档,当云词图很大的,加大该值会比使用更大的图更快,但值越高也会越慢(计算更复杂)。默认值是1。

random_state:不同的值会让字图的分布不一样。

三、使用tkinter库进行可视化展现

先看看效果图:

有两块内容分别进行处理:

先说第一块:需要实现选择文件功能,其中选择文件分别包括:词频统计的文本文件、背景图文件和需要保存的词云图。

1、实现打开文件对话框,并针对异常报错。

from tkinter import messagebox as msgbox def load_src_file(*args): localfile = filedialog.askopenfile(title='打开单个文件', filetypes=[("文本文件","*.txt")],# 只处理的文件类型 initialdir='D:/') if(localfile): openfile.delete(0,END) openfile.insert(END,localfile.name) else: msgbox.showinfo(message=('读取文件异常')) def load_src_file1(*args): localfile = filedialog.askopenfile(title='打开单个文件', filetypes=[("图片文件", "*.jpg"), ('图片文件', '*.png')],# 只处理的文件类型 initialdir='D:/') if(localfile): openfile2.delete(0,END) openfile2.insert(END,localfile.name) else: msgbox.showinfo(message=('读取文件异常')) def save_out_file(*args): localfile = filedialog.asksaveasfile(title='保存文件', filetypes=[("图片文件", "*.jpg"), ('图片文件', '*.png')], # 只处理的文件类型 initialdir='D:/') if(localfile): savefile.delete(0,END) savefile.insert(END,localfile.name) else: msgbox.showinfo(message=('读取文件异常'))

2、使用treeview控件显示词云图:

(1)设置表格:

col = [1, 2] tree = ttk.Treeview(tab2, columns=col, height=10, show="headings") tree.column('0', width=150, anchor='center') # 指定第一列的宽度和名称, 如果show = "headings", 这一列就被隐藏。 tree.column('1', width=100, anchor='center') tree.column('2', width=100, anchor='w') tree.heading('0', text='column0') tree.heading('1', text='关键词') tree.heading('2', text='出现次数')

(2)清空表格

def add_tree(self,list, tree): #新增数据到表格 i = 0 for subList in list: tree.insert('', 'end', values=subList) i = i + 1

(3)添加表格数据

def add_tree(self,list, tree): #新增数据到表格 i = 0 for subList in list: tree.insert('', 'end', values=subList) i = i + 1

举例如下:

from tkinter import * import tkinter.ttk as ttk win = Tk() win.title("Treeview") col = [1, 2] data = {"item0": ["1a", "2a"],"item2": ["1c", "2c"]} tree = ttk.Treeview(win, columns=col, height=10, show="headings") tree.column('0', width=150, anchor='center') # 指定第一列的宽度和名称, 如果show = "headings", 这一列就被隐藏。 tree.column('1', width=100, anchor='center') tree.column('2', width=100, anchor='w') tree.heading('0', text='column0') tree.heading('1', text='关键词') tree.heading('2', text='出现次数') tree.insert('', 'end', values=data["item0"]) tree.insert('', 'end', values=data["item2"]) tree.pack(expand=Y,fill=BOTH) win.mainloop()

运行效果如下:

3、Progressbar的实现

from tkinter import * from tkinter import filedialog, ttk root = Tk() # 创建一个Tkinter.Tk()实例 root.title('消息') root.geometry('600x300+450+200') def up(i): mpb["value"] = i%20 i+=1 root.after(100, up,i) # 每隔1s调用函数up更新控件信息 Label(root, text='正在处理中,请稍候...', fg='red').pack() mpb = ttk.Progressbar(root, orient="horizontal", length=200, mode="indeterminate") mpb.pack() mpb["maximum"] = 20 mpb["value"] = 0 up(0) root.mainloop()

输出效果如下:

四、使用多线程技术进行异步监听加载

这个部分将会在多线程的文章中进行讲解,敬请期待。

相关代码如下:(暂不包含多线程的相关代码)

from tkinter import * from tkinter import filedialog from tkinter import ttk from PIL import Image,ImageTk import cv2 import base_final import time from tkinter import messagebox as msgbox def center_window( root, w, h): # 获取屏幕 宽、高 ws = root.winfo_screenwidth() hs = root.winfo_screenheight() # 计算 x, y 位置 x = (ws / 2) - (w / 2) y = (hs / 2) - (h / 2) root.geometry('%dx%d+%d+%d' % (w, h, x, y)) def load_src_file(*args): localfile = filedialog.askopenfile(title='打开单个文件', filetypes=[("文本文件","*.txt")],# 只处理的文件类型 initialdir='D:/') if(localfile): openfile.delete(0,END) openfile.insert(END,localfile.name) else: msgbox.showinfo(message=('读取文件异常')) def load_src_file1(*args): localfile = filedialog.askopenfile(title='打开单个文件', filetypes=[("图片文件", "*.jpg"), ('图片文件', '*.png')],# 只处理的文件类型 initialdir='D:/') if(localfile): openfile2.delete(0,END) openfile2.insert(END,localfile.name) else: msgbox.showinfo(message=('读取文件异常')) def save_out_file(*args): localfile = filedialog.asksaveasfile(title='保存文件', filetypes=[("图片文件", "*.jpg"), ('图片文件', '*.png')], # 只处理的文件类型 initialdir='D:/') if(localfile): savefile.delete(0,END) savefile.insert(END,localfile.name) else: msgbox.showinfo(message=('读取文件异常')) def onclick(*args): global data source_file = openfile.get() result_file = savefile.get() source_image = openfile2.get() top_level = Toplevel(root) top_level.geometry('200x50') top_level.title('Sign up window') Label(top_level, text='正在处理中,请稍候...', fg='blue',font=("微软雅黑",15)).pack() mpb = ttk.Progressbar(top_level, orient="horizontal",length=200, mode="indeterminate") mpb.pack() mpb["maximum"] = 20 mpb["value"] = 0 top_level.overrideredirect(1) # 去除窗口边框 top_level.wm_attributes("-alpha", 0.9) # 透明度(0.0~1.0) top_level.wm_attributes("-toolwindow", True) # 置为工具窗口(没有最大最小按钮) top_level.wm_attributes("-topmost", True) # 永远处于顶层 center_window(top_level, 200, 150) top_level.update() def up(i): flag = base_1.get_flag() while flag: mpb["value"] = (i + 1) % 20 i += 1 flag = base_1.get_flag() top_level.update() time.sleep(0.1) data = base_1.get_result() top_level.destroy() return data base_1 = base_final.base_run(source_file, source_image,result_file) base_1.setDaemon(True) # 设置守护进程,主线程结束时,不管子线程有没有结束都会退出进程 base_1.start() data = up(0) img = cv2.imread(result_file) cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) current_image = Image.fromarray(cv2image) # 将图像转换成Image对象 pil_image_resized = resize(430, 500, current_image) # 等比例缩放本地图片 # imgtk = ImageTk.PhotoImage(word_cloud) imgtk = ImageTk.PhotoImage(pil_image_resized) label1.imgtk = imgtk label1.config(image=imgtk) for i in data: tree.insert('', 'end', values=[i[0],i[1]]) def resize(w_box, h_box, pil_image): f1 = 1.0 * w_box / pil_image.size[0] # 1.0 forces float division in Python2 f2 = 1.0 * h_box / pil_image.size[1] factor = min([f1, f2]) width = int(pil_image.size[0] * factor) height = int(pil_image.size[1] * factor) return pil_image.resize((width, height), Image.ANTIALIAS) root=Tk() root.title('词频统计小工具V1.0版') center_window(root,420,500) #初始化操作区控件 top_frame = ttk.LabelFrame(root,text='操作区') open_button = Button(top_frame, text='请选择打开文件',command=load_src_file) open_button.grid(row=0, sticky="w") openfile = ttk.Entry(top_frame, width=30, font=('StSong',14), foreground='green') openfile.insert(END,'./zyds.txt') openfile.grid(row=0, column=1) open_button2 = Button(top_frame, text='请选择打开文件', command=load_src_file1) open_button2.grid(row=1, sticky="w") openfile2 = ttk.Entry(top_frame, width=30, font=('StSong', 14), foreground='green') openfile2.insert(END, './timg1.jpg') openfile2.grid(row=1, column=1) save_button = Button(top_frame, text='请选择保存文件',command=save_out_file) save_button.grid(row=2, sticky="w") savefile = ttk.Entry(top_frame, width=30, font=('StSong',14), foreground='green') savefile.insert(END,'./out.jpg') savefile.grid(row=2, column=1) login = Button(top_frame,text='提交\n处理',command=onclick) login.grid(row=0, column=2, rowspan=3, padx=5, pady=5) top_frame.pack(side='top') #初始化图像显示控件 tabControl = ttk.Notebook(root) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab label1=Label(tab1,text='欢迎使用词频统计小工具V1.0版!') label1.pack() tabControl.add(tab1, text='词云图') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='top10词频统计') # Make second tab visible col = [1, 2] tree = ttk.Treeview(tab2, columns=col, height=10, show="headings") tree.column('0', width=150, anchor='center') # 指定第一列的宽度和名称, 如果show = "headings", 这一列就被隐藏。 tree.column('1', width=100, anchor='center') tree.column('2', width=100, anchor='w') tree.heading('0', text='column0') tree.heading('1', text='关键词') tree.heading('2', text='出现次数') vbar = ttk.Scrollbar(tree, command=tree.yview) tree.configure(yscrollcommand=vbar.set) vbar.pack(side=RIGHT, fill=Y) tree.pack(expand=Y,fill=BOTH) ll = Label(tab2,text='欢迎使用词频统计小工具V1.0版!') ll.pack(side='left') tabControl.pack(expand=Y,fill=BOTH) root.mainloop()

最后出来的效果如下:


作者:dhjabc_1



云图 自定义 词云 tkinter top Python

需要 登录 后方可回复, 如果你还没有账号请 注册新账号