项目简介
这个食堂数据分析应用程序通过Tkinter GUI提供了直观的界面,让用户能够浏览、比较和分析不同食堂的关键数据。用户可以查看各食堂的人均消费排名,了解特定食堂的菜品受欢迎程度,并根据不同标准(如周人流量、周营业额、投诉情况等)进行排名。此外,应用程序还展示了投诉情况的分布。通过提供交互式操作,用户能够选择关注的食堂和排名标准。
效果展示
数据纵览
总.xlsx
田园菜单.xlsx、百业菜单.xlsx、龙山菜单.xlsx的数据格式都大致如下。
项目思路
- 加载数据:
- 从Excel文件加载总体数据到名为zong的数据框。
- 从Excel文件加载田园菜单数据到名为TainYuan的数据框。
- 从Excel文件加载百业菜单数据到名为BaiYe的数据框。
- 从Excel文件加载龙山菜单数据到名为LongShan的数据框。
- 创建Tkinter窗口:
- 创建一个Tkinter窗口并设置标题为“食堂数据分析”。
- 定义显示排名的函数:
- display_ranking函数用于显示基于人均消费的食堂排名。
- display_menu_ranking函数用于显示特定食堂菜品排名。
- display_ranking_criteria函数用于显示指定标准的排名。
- display_complaint_distribution函数用于显示投诉情况的饼图。
- 定义按钮点击事件函数:
- button_click函数处理按钮点击事件,根据所选食堂调用相应的显示函数。
- 创建菜单栏:
- 创建菜单栏包括排名标准和食堂选项的子菜单。
- 设置排名标准的菜单项选择:
- 为排名标准创建子菜单,并定义选择该项时的回调函数。
- 设置食堂选项的菜单:
- 为食堂选项创建子菜单,并定义选择该项时的回调函数。
- 显示初始排名:
- 使用display_ranking_criteria函数显示初始的人均消费排名。
- 处理投诉情况分布:
- 使用display_complaint_distribution函数显示投诉情况分布。
- 运行Tkinter事件循环:
- 启动Tkinter的事件循环,使窗口可以响应用户操作。
代码具体实现
加载数据
# 从Excel文件加载总体数据到名为zong的数据框
zong = pd.read_excel('总.xlsx')
# 从Excel文件加载田园菜单数据到名为TainYuan的数据框
TainYuan = pd.read_excel('田园菜单.xlsx')
# 从Excel文件加载百业菜单数据到名为BaiYe的数据框
BaiYe = pd.read_excel('百业菜单.xlsx')
# 从Excel文件加载龙山菜单数据到名为LongShan的数据框
LongShan = pd.read_excel('龙山菜单.xlsx')
创建Tkinter窗口
- tk.Tk() 是tkinter库中用于创建主窗口的函数。
- window 是创建的Tkinter窗口的实例,通过该窗口用户可以与应用程序进行交互。
- window.title(“食堂数据分析”) 设置了窗口的标题为“食堂数据分析”。
这段代码的作用是创建一个Tkinter窗口,为食堂数据分析应用程序的图形
# 创建Tkinter窗口
window = tk.Tk()
# 设置Tkinter窗口标题
window.title("食堂数据分析")
定义显示排名的函数
- display_ranking 函数用于显示基于人均消费的食堂排名的水平条形图。
- plt.barh 绘制水平条形图,颜色为’#3498db’,边缘为黑色。
- plt.text 用于在条形图上标注每个数据点的数值。
- 图表的标题、标签和网格通过 plt.title、plt.ylabel 和 plt.grid 进行设置。
- FigureCanvasTkAgg 类将Matplotlib图表嵌入到Tkinter窗口中,并通过 canvas.draw() 刷新图表。
这个函数的目的是在Tkinter窗口中显示基于人均消费的食堂排名图表。其他几个函数(display_menu_ranking、display_ranking_criteria、display_complaint_distribution)的实现与display_ranking 类似,主要是根据不同的数据和标准生成相应的图表。这些函数的共同点是利用Matplotlib创建图表,然后通过Tkinter将图表嵌入到窗口中,实现在GUI中显示相应的数据可视化。
# 函数:显示基于人均消费的食堂排名
def display_ranking(df, title):
# 清除先前的图表
plt.clf()
# 创建具有指定大小和背景颜色的新图表
plt.figure(figsize=(9, 3.5), facecolor=bg_color_hex)
# 绘制水平条形图,显示人均消费
plt.barh(df['餐厅名称'], df['人均消费'], color='#3498db', \
edgecolor='black', linewidth=0.5)
# 用值注释数据点
for index, value in enumerate(df['人均消费']):
plt.text(value, index, f'{
value:.2f} 元', ha='left', \
va='center', fontsize=10)
# 设置图表的标题、标签和网格
plt.title(title + '人均消费排名', fontsize=14, fontweight='bold')
plt.ylabel('餐厅名称', fontsize=12)
plt.grid(axis='x', linestyle='--', alpha=0.6)
# 在Tkinter窗口中显示图表
canvas = FigureCanvasTkAgg(plt.gcf(), master=window)
canvas.draw()
# 销毁先前的画布,以避免重叠
if hasattr(display_ranking, 'tk_canvas'):
display_ranking.tk_canvas.get_tk_widget().destroy()
canvas.get_tk_widget().pack()
# 保存新画布以供将来参考
display_ranking.tk_canvas = canvas
定义按钮点击事件函数
- button_click 函数是一个按钮点击事件的处理函数,根据所选的食堂调用相应的显示函数。
- 在该函数中,根据 cafeteria 参数的值(按钮的标签),调用不同的显示函数(例如,display_menu_ranking)并传入相应的食堂数据和标题。
这个函数的目的是在用户点击相应食堂按钮时,根据所选食堂调用相应的显示函数,显示该食堂的排名或其他相关信息的图表。
# 函数:处理按钮点击事件
def button_click(cafeteria):
# 根据所选食堂调用display_menu_ranking函数
if cafeteria == '田园菜单':
display_menu_ranking(TainYuan, '田园食堂')
elif cafeteria == '百业菜单':
display_menu_ranking(BaiYe, '百业广场')
elif cafeteria == '龙山菜单':
display_menu_ranking(LongShan, '龙山食堂')
创建菜单栏
- tk.Menu(window) 创建了一个菜单栏。
- tk.Menu(menu_bar, tearoff=0) 创建了排名标准的子菜单,并通过 tearoff 参数设置为不允许拆分。
- ranking_menu.add_command 添加了不同的排名标准选项,并通过 command 参数定义了选择该项时的回调函数。
- 类似地,创建了食堂选项的子菜单 cafeteria_menu,并添加了不同食堂的选项。
这段代码的目的是创建一个Tkinter菜单栏,包括排名标准和食堂选项的子菜单,使用户能够通过菜单选择不同的排名标准和食堂,实现更灵活的数据查看和分析。
# 创建菜单栏
menu_bar = tk.Menu(window)
# 创建排名标准的菜单
ranking_menu = tk.Menu(menu_bar, tearoff=0)
# 将排名标准选项添加到菜单中
# 将“周人流量排名”添加到排名标准菜单,并定义选择该项时的回调函数
ranking_menu.add_command(label="周人流量排名", \
command=lambda: menu_select_criteria('周人流量'))
# 将“周营业额排名”添加到排名标准菜单,并定义选择该项时的回调函数
ranking_menu.add_command(label="周营业额排名", \
command=lambda: menu_select_criteria('周营业额'))
# ... (其他排名标准的添加类似)
# 将排名标准菜单添加到菜单栏
menu_bar.add_cascade(label="排名", menu=ranking_menu)
# 创建食堂选项的菜单
cafeteria_menu = tk.Menu(menu_bar, tearoff=0)
# 将食堂选项添加到菜单中
# 向食堂选项菜单中添加“田园菜单”命令,并定义选择该项时的回调函数
cafeteria_menu.add_command(label="田园菜单", \
command=lambda: button_click('田园菜单'))
# 向食堂选项菜单中添加“百业菜单”命令,并定义选择该项时的回调函数
cafeteria_menu.add_command(label="百业菜单", \
command=lambda: button_click('百业菜单'))
# ... (其他食堂的添加类似)
# 将食堂菜单添加到菜单栏
menu_bar.add_cascade(label="食堂菜单", menu=cafeteria_menu)
# 为窗口设置菜单栏
window.config(menu=menu_bar)
设置排名标准的菜单项选择
- menu_select_criteria 函数是排名标准菜单项选择时的回调函数,根据选择的标准调用 display_ranking_criteria 函数显示相应的排名图表。
- 在创建排名标准的菜单时,通过 add_command 为每个排名标准添加一个菜单项,并通过 command 参数指定选择该项时调用的回调函数。
这段代码的目的是为排名标准创建一个子菜单,使用户能够通过菜单选择不同的排名标准,并实时查看相应的排名图表。
# 函数:处理排名标准的菜单项选择
def menu_select_criteria(column):
display_ranking_criteria(zong, column, '食堂')
# 创建排名标准的菜单
ranking_menu = tk.Menu(menu_bar, tearoff=0)
# 将排名标准选项添加到菜单中
# 将“周人流量排名”添加到排名标准菜单,并定义选择该项时的回调函数
ranking_menu.add_command(label="周人流量排名", \
command=lambda: menu_select_criteria('周人流量'))
# 将“周营业额排名”添加到排名标准菜单,并定义选择该项时的回调函数
ranking_menu.add_command(label="周营业额排名", \
command=lambda: menu_select_criteria('周营业额'))
# ... (其他排名标准的添加类似)
# 将排名标准菜单添加到菜单栏
menu_bar.add_cascade(label="排名", menu=ranking_menu)
设置食堂选项的菜单
- button_click 函数是食堂选项菜单项选择时的回调函数,根据选择的食堂调用 display_menu_ranking 函数显示相应的菜品排名图表。
- 在创建食堂选项的菜单时,通过 add_command 为每个食堂添加一个菜单项,并通过 command 参数指定选择该项时调用的回调函数。
这段代码的目的是为食堂选项创建一个子菜单,使用户能够通过菜单选择不同的食堂,并实时查看相应的菜品排名图表。
# 函数:处理食堂选项的菜单项选择
def button_click(cafeteria):
# 根据所选食堂调用display_menu_ranking函数
if cafeteria == '田园菜单':
display_menu_ranking(TainYuan, '田园食堂')
elif cafeteria == '百业菜单':
display_menu_ranking(BaiYe, '百业广场')
elif cafeteria == '龙山菜单':
display_menu_ranking(LongShan, '龙山食堂')
# 创建食堂选项的菜单
cafeteria_menu = tk.Menu(menu_bar, tearoff=0)
# 将食堂选项添加到菜单中
# 向食堂选项菜单中添加“田园菜单”命令,并定义选择该项时的回调函数
cafeteria_menu.add_command(label="田园菜单", \
command=lambda: button_click('田园菜单'))
# 向食堂选项菜单中添加“百业菜单”命令,并定义选择该项时的回调函数
cafeteria_menu.add_command(label="百业菜单", \
command=lambda: button_click('百业菜单'))
# ... (其他食堂的添加类似)
# 将食堂菜单添加到菜单栏
menu_bar.add_cascade(label="食堂菜单", menu=cafeteria_menu)
显示初始排名
- 在窗口创建后,通过调用 display_ranking_criteria 函数显示初始的人均消费排名图表。
- 传入参数 zong 表示总体数据框,‘人均消费’ 表示选择的排名标准,‘食堂’ 表示在图表标题中添加的附加信息。
这段代码的目的是在程序运行后,自动显示初始的人均消费排名图表,为用户提供了初始的数据分析结果。
# 显示初始的人均消费排名
display_ranking_criteria(zong, '人均消费', '食堂')
处理投诉情况分布
- 导入了用于计算投诉分布的模块 collections 中的 Counter 类。
- display_complaint_distribution 函数用于显示投诉情况分布的饼图。
- 在该函数中,首先使用 Counter 类计算数据框中投诉情况的分布情况。
- 然后使用 Matplotlib 绘制饼图,显示投诉情况的分布情况。
- 最后将绘制的图表嵌入到 Tkinter 窗口中显示。
这段代码的作用是实现了处理投诉情况分布的功能,通过饼图形式展示了投诉情况的分布情况。
# 导入用于计算投诉分布的所需模块
from collections import Counter
# 函数:显示投诉分布的饼图
def display_complaint_distribution(df, title):
# 获取投诉分布
complaints_distribution = Counter(df['投诉情况'])
# 创建具有指定大小和背景颜色的新图表
plt.figure(figsize=(8, 8), facecolor=bg_color_hex)
# 绘制投诉分布的饼图
plt.pie(complaints_distribution.values(), \
labels=complaints_distribution.keys(), \
autopct='%1.1f%%', startangle=140)
# 为图表设置标题
plt.title(title + '投诉情况分布', fontsize=14, fontweight='bold')
# 在Tkinter窗口中显示图表
canvas = FigureCanvasTkAgg(plt.gcf(), master=window)
canvas.draw()
# 销毁先前的画布,以避免重叠
if hasattr(display_complaint_distribution, 'tk_canvas'):
display_complaint_distribution.tk_canvas.get_tk_widget().destroy()
canvas.get_tk_widget().pack()
# 保存新画布以供将来参考
display_complaint_distribution.tk_canvas = canvas
运行Tkinter事件循环
- window.mainloop() 启动了 Tkinter 的事件循环,使窗口可以响应用户的各种操作,包括按钮点击、菜单选择等。
- 一旦调用 mainloop(),程序将进入一个无限循环,等待用户的交互事件,并在发生事件时执行相应的操作。
# 运行Tkinter事件循环
window.mainloop()
项目链接
GitHub:https://github.com/Olivia-account/CampusCanteenAnalytics-tk
后记
如果觉得有帮助的话,求 关注、收藏、点赞、星星 哦!
文章评论