(5-5)绘制饼状图:可视化展示名著《西游记》中出现频率最多的文字

5.4  可视化展示名著《西游记》中出现频率最多的文字

在数据可视化分析领域中,文字识别和统计处理是最常用的一种应用情形。在本节的内容中,将在记事本文件中保存四大名著之一的《西游记》电子书,然后对这个记事本文件进行计数测试,最后使用饼状图展示出现频率最多的文字。

5.4.1  单元测试文件

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。在本项目中的“test”目录下保存了单元测试文件,各个文件的主要功能如下所示:

  1. test_arc.py:功能是实现matplotlib.pyplot绘图测试。
  2. test_embedded_tk.py:功能是实现tkinter窗体内嵌pyplot测试。
  3. test_thread.py:功能是实现多线程绘图测试。
  4. wordCount.py:功能是实现文本文件计数测试。
  5. wordGenerate.py:功能是实现生成测试所用文本文件。

5.4.2  GUI界面

本项目是使用Python GUI界面库Tkinter实现的,为了提高统计小说文字的效率,使用内置库threading实现多线程处理。编写程序文件MainWindow.py实现本项目的UI界面,具体实现流程如下所示。

(1)编写类MainWindow实现主窗体,在顶部设计一个“打开文件”菜单。对应的实现代码如下所示。

class MainWindow:
    def __init__(self):
        self.root = tk.Tk()  # 创建主窗体
        self.root.geometry("600x500")
        menubar = tk.Menu(self.root)
        self.canvas = tk.Canvas(self.root)
        menubar.add_command(label='打开文件', command=self.open_file_dialog)
        self.root['menu'] = menubar
        self.expected_percentage = 0.8

(2)编写函数open_file_dialog(self),单击“打开文件”菜单后会弹出一个打开文件对话框。函数open_file_dialog(self)的具体实现代码如下所示。

    def open_file_dialog(self):
        file = tk.filedialog.askopenfilename(title='打开文件', filetypes=[('text', '*.txt'), ('All Files', '*')])
        self.dialog = InputDialog.InputDialog(self)
        self.dialog.mainloop()
        load_thread = threading.Thread(target=self.create_matplotlib, args=(file,))
        load_thread.start()

(3)编写函数create_matplotlib(self, f),功能是使用Matplotlib绘制饼状图,首先设置字体为“SimHei”,然后使用函数open()打开要读取的文件,通过循环统计记事本文件中的所有文字,最终根据统计结果绘制饼状图。为了提高效率,特意使用了以下两种机制:

  1. 利用re模块进行正则匹配筛选文本,简化代码编写量。
  2. 利用threading模块实现多线程读取文件并进行文字统计,从而不影响窗体循环,使得用户可以继续进行操作。

函数create_matplotlib(self, f)的具体实现代码如下所示。

    def create_matplotlib(self, f):
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        plt.style.use("ggplot")

        file = open(f, 'r', encoding='utf-8')
        word_list = list(file.read())
        word_count = {}
        total_words = 0
        for word in word_list:
            if re.match('\\w', word):
                total_words += 1
                if word in word_count:
                    word_count[word] += 1
                else:
                    word_count[word] = 1
        max_list = []
        max_count = []
        now_percentage = 0
        if self.expected_percentage >= 1:
            while len(word_count) != 0:
                max_count.append(0)
                max_list.append("")
                for word, count in word_count.items():
                    if max_count[-1] < count:
                        max_count[-1] = count
                        max_list[-1] = word
                # if max_list[-1] in word_count:
                word_count.pop(max_list[-1])
        else:
            while now_percentage < self.expected_percentage:
                max_count.append(0)
                max_list.append("")
                for word, count in word_count.items():
                    if max_count[-1] < count:
                        max_count[-1] = count
                        max_list[-1] = word
                # if max_list[-1] in word_count:
                word_count.pop(max_list[-1])
                now_percentage = 0
                for val in max_count:
                    now_percentage += val / total_words

        print(max_list, [val / total_words for val in max_count], sep="\n")

        fig = plt.figure(figsize=(32, 32))
        ax1 = fig.add_subplot(111)
        tuple_builder = [0.0 for index in range(len(max_count))]
        tuple_builder[0] = 0.1
        explode = tuple(tuple_builder)
        ax1.pie(max_count, labels=max_list, autopct='%1.1f%%', explode=explode, textprops={'size': 'larger'})
        ax1.axis('equal')
        ax1.set_title('文字统计')

        self.create_form(fig)

(4)编写函数create_form(self, figure),使用Tkinter的canvas绘制pyplot,然后利用库Matplotlib提供的NavigationToolbar2Tk将pyplot的导航栏内嵌到tkinter窗体中。函数create_form(self, figure)的具体实现代码如下所示。

    def create_form(self, figure):
        self.clear()
        figure_canvas = FigureCanvasTkAgg(figure, self.root)
        self.canvas = figure_canvas.get_tk_widget()

        self.toolbar = NavigationToolbar2Tk(figure_canvas, self.root)
        self.toolbar.update()
        self.canvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

(5)编写函数clear(self)销毁创建的工具栏,在主函数中启动GUI界面。函数clear(self)的具体实现代码如下所示。

    def clear(self):
        self.canvas.destroy()
        if hasattr(self, 'toolbar'):
            self.toolbar.destroy()


if __name__ == "__main__":
    mainWindow = MainWindow()
    mainWindow.root.mainloop()

执行文件MainWindow.py后会启动GUI主界面,执行效果如图5-19所示。单击GUI主界面菜单中的“打开文件”后会弹出一个“打开文件”对话框,如图5-20所示。

                    图5-19  GUI主界面                                             图5-20  “打开文件”对话框

5.4.3  设置所需显示的出现频率

编写文件InputDialog.py,功能是当在“打开文件”对话框中选择一个要统计的小说文件后会弹出一个输入对话框,提示用户输入所需显示的出现频率,然后根据用户输入的频率值统计文字。文件InputDialog.py的具体实现代码如下所示。

import tkinter as tk

class InputDialog(tk.Tk):

    def __init__(self, main_window):
        tk.Tk.__init__(self)
        self.main_window = main_window
        tk.Label(self, text="输入所需显示的出现频率百分数:").grid(row=0, column=0)
        self.input = tk.Entry(self, bd=5)
        self.input.insert(0, "20%")
        self.input.grid(row=0, column=1)
        tk.Button(self, text="Commit", command=self.__commit).grid(row=1, column=0, columnspan=2, padx=5, pady=5)

    def __commit(self):
        self.main_window.expected_percentage = float(self.input.get().strip("%"))/100
        self.quit()
        self.withdraw()


if __name__ == '__main__':
    window = MainWindow.MainWindow()
    window.root.mainloop()

执行后的效果如图5-21所示,这说明本项目默认的统计频率值是20%。单击“Commit”按钮后会在“输出”界面打印显示下面的统计结果,并统计当前文件中频率为20%的文字的统计饼状图,如图5-22所示。

['道', '不', '一', '了', '那', '我', '是', '来', '他', '个', '行', '你', '的', '者', '有', '大', '得', '这', '上', '去']
[0.018718106708697443, 0.01499729364466065, 0.013463692285695805, 0.013073909032418393, 0.012735189087430597, 0.012141152600994713, 0.010975207061715115, 0.010103726600238977, 0.009727560229172127, 0.009656071597566663, 0.00958968929679016, 0.009308841101197264, 0.009182884940749541, 0.008502040830221309, 0.007553965406310744, 0.00724928766684936, 0.006478231711676136, 0.006445891616426045, 0.006292701691557193, 0.006214404618846446]

                    图5-21  默认值是20%                                                 图5-22  统计饼状图

祝福大家中秋节快乐:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值