Python数据分析实战:微信好友可视化 + 23级学生成绩分析,含GUI界面和打包exe
一、项目背景与设计思想
随着大数据时代的到来,数据分析能力已成为软件专业学生的核心竞争力。本次项目旨在通过Python技术栈,完成对“微信好友数据”和“23级学生信息”的双维度分析。
设计思想:
1. 模块化设计:将微信分析、学生分析、GUI界面分离,提高代码复用性。
2. 数据可视化驱动:利用图表(饼图、柱状图、词云)直观展示数据背后的规律,例如通过分析好友地域分布了解社交圈构成,通过分析学生成绩评估教学效果。
3. 用户体验优先:利用 tkinter 构建 GUI 界面,非技术人员也能一键运行;最终利用 PyInstaller 打包为 exe,无需安装 Python 环境即可运行。
二、核心功能实现
1. 微信好友数据分析:
数据模拟:由于 itchat 接口限制,项目采用 pandas 构建模拟数据集,包含昵称、性别、省份、签名等字段。
性别与地域分析:利用 matplotlib 绘制饼图和横向柱状图,直观展示好友属性。
文本挖掘:利用 wordcloud 库对好友签名进行词云化处理,提取高频词汇,洞察好友的兴趣爱好。
2. 23级学生数据分析:
成绩分布:绘制直方图观察 Python、数学、英语成绩是否符合正态分布。
专业对比:通过分组聚合计算各专业平均分,评估不同专业的学业水平。
优秀生识别:利用 pandas 的 nlargest 方法筛选总分前十的学生,并生成荣誉榜单。
3. 系统集成与打包:
使用 tkinter 搭建交互界面,绑定各分析事件。
使用 subprocess 或直接调用模块函数实现“一键生成所有报告”。
利用 PyInstaller -F -w 命令打包为单文件 exe,方便分发。
三、关键代码展示
项目结构
WeChat_Student_Analysis/
│── data/
│ │── fake_wechat_data.csv # 模拟的微信好友数据
│ │── students_data.csv # 23级学生信息数据
│── main_gui.py # 主程序入口
│── wechat_analysis.py # 微信数据分析模块
│── student_analysis.py # 学生数据分析模块
│── requirements.txt # 依赖库列表
│── run.spec # 打包配置文件
第一部分:核心代码
1. 数据模拟与准备 (data_generator.py)
import pandas as pd
import random
from collections import Counter
# 中文姓名词库
names = ['王明', '李芳', '张伟', '刘强', '陈丽', '赵磊', '周敏', '吴刚', '郑洁', '林晨',
'郭峰', '唐雅', '孙鹏', '宋阳', '徐璐', '黄鑫', '马瑶', '朱莉', '胡宇', '林娜']
provinces = ['广东', '北京', '上海', '浙江', '江苏', '四川', '湖北', '湖南', '福建', '山东']
cities = {
'广东': ['广州', '深圳', '佛山'], '北京': ['北京市'], '上海': ['上海市'],
'浙江': ['杭州', '宁波'], '江苏': ['南京', '苏州'], '四川': ['成都'],
'湖北': ['武汉'], '湖南': ['长沙'], '福建': ['福州'], '山东': ['济南']
}
signatures = ['人生苦短,我用Python', '数据分析师', '努力学习中', '爱生活', 'Just Do It',
'Hello World', '开心每一天', 'coding', '读书', '健身', '美食']
avatars = ['avatar1.png', 'avatar2.png'] # 模拟头像路径
def generate_fake_wechat():
"""生成模拟微信好友数据"""
data = []
for i in range(1, 201): # 模拟200个好友
sex = random.choice(['Male', 'Female'])
province = random.choice(provinces)
city = random.choice(cities[province]) if province in cities else '未知'
friend = {
'NickName': random.choice(names) + str(random.randint(1, 100)),
'Sex': sex,
'Province': province,
'City': city,
'Signature': random.choice(signatures),
'RemarkName': '' if random.random() > 0.3 else '特别关注_' + str(i) # 30%的人有备注
}
data.append(friend)
df = pd.DataFrame(data)
df.to_csv('data/fake_wechat_data.csv', index=False, encoding='utf-8-sig')
print("微信模拟数据生成完成!")
def generate_fake_students():
"""生成模拟23级学生数据"""
grades = [85, 92, 78, 88, 95, 67, 59, 100, 82, 75] * 5
data = []
majors = ['软件工程', '计算机科学', '数据科学', '人工智能', '网络工程']
for i in range(1, 51): # 50个学生
student = {
'学号': f'2023{str(i).zfill(4)}',
'姓名': random.choice(names) + ('' if i%2==0 else random.choice(['A','B'])),
'专业': random.choice(majors),
'数学成绩': random.randint(60, 98),
'Python成绩': random.randint(55, 100),
'英语成绩': random.randint(65, 95),
'性别': random.choice(['男', '女'])
}
data.append(student)
df = pd.DataFrame(data)
df.to_csv('data/students_data.csv', index=False, encoding='utf-8-sig')
print("学生模拟数据生成完成!")
if __name__ == '__main__':
generate_fake_wechat()
generate_fake_students()
2. 微信数据分析核心 (wechat_analysis.py)
实现要求:性别可视化、省份可视化、城市可视化、特殊好友可视化、签名词云化。
import pandas as pd
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import numpy as np
from collections import Counter
import os
# 设置中文字体,解决乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'WenQuanYi Micro Hei']
plt.rcParams['axes.unicode_minus'] = False
class WeChatAnalyzer:
def __init__(self):
self.df = None
self.load_data()
def load_data(self):
if os.path.exists('data/fake_wechat_data.csv'):
self.df = pd.read_csv('data/fake_wechat_data.csv')
else:
# 如果没有生成数据,自动生成
from data_generator import generate_fake_wechat
generate_fake_wechat()
self.df = pd.read_csv('data/fake_wechat_data.csv')
print("微信数据加载成功")
def plot_sex_distribution(self, save_path='wechat_sex.png'):
"""1. 性别可视化 (饼图/柱状图)"""
sex_counts = self.df['Sex'].value_counts()
plt.figure(figsize=(8, 6))
plt.pie(sex_counts, labels=sex_counts.index, autopct='%1.1f%%', startangle=90, colors=['#FF69B4', '#1E90FF'])
plt.title('微信好友性别分布', fontsize=16)
plt.savefig(save_path, dpi=100, bbox_inches='tight')
plt.close()
return save_path
def plot_province_distribution(self, save_path='wechat_province.png'):
"""2. 所在省份可视化 (横向柱状图 Top 10)"""
province_counts = self.df['Province'].value_counts().head(10)
plt.figure(figsize=(10, 6))
province_counts.plot(kind='barh', color='skyblue')
plt.title('微信好友所在省份分布 (Top 10)', fontsize=16)
plt.xlabel('好友数量')
plt.gca().invert_yaxis()
plt.tight_layout()
plt.savefig(save_path, dpi=100)
plt.close()
return save_path
def plot_city_distribution(self, save_path='wechat_city.png'):
"""3. 所在城市可视化"""
city_counts = self.df['City'].value_counts().head(10)
plt.figure(figsize=(12, 6))
city_counts.plot(kind='bar', color='lightcoral')
plt.title('微信好友所在城市分布 (Top 10)', fontsize=16)
plt.xlabel('城市')
plt.ylabel('好友数量')
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig(save_path, dpi=100)
plt.close()
return save_path
def plot_special_friends(self, save_path='wechat_special.png'):
"""4. 特殊好友可视化 (有备注名的认为是特殊好友)"""
# 假设有备注名的为特别好友
self.df['IsSpecial'] = self.df['RemarkName'].notna() & (self.df['RemarkName'] != '')
special_count = self.df['IsSpecial'].value_counts()
labels = ['特殊关注好友', '普通好友']
sizes = [special_count.get(True, 0), special_count.get(False, 0)]
plt.figure(figsize=(7, 7))
explode = (0.1, 0) # 突出显示特殊好友
plt.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True, startangle=90)
plt.title('特殊好友占比分析', fontsize=16)
plt.savefig(save_path, dpi=100)
plt.close()
return save_path
def generate_wordcloud(self, save_path='wechat_wordcloud.png'):
"""5. 签名词云化"""
# 合并所有签名,去除空值
text = ' '.join(self.df['Signature'].dropna().astype(str))
if not text:
text = "Python 数据分析 微信 好友 可视化 项目"
wordcloud = WordCloud(width=800, height=400,
background_color='white',
font_path='simhei.ttf', # Windows系统可指定,Mac/Linux需调整或去掉
colormap='viridis',
max_words=100).generate(text)
plt.figure(figsize=(10, 5))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.title('微信好友个性签名词云', fontsize=16)
plt.savefig(save_path, dpi=100)
plt.close()
return save_path
if __name__ == '__main__':
wc = WeChatAnalyzer()
wc.plot_sex_distribution()
wc.plot_province_distribution()
wc.plot_city_distribution()
wc.plot_special_friends()
wc.generate_wordcloud()
print("微信数据分析图表已生成")
3. 学生信息分析核心 (student_analysis.py)
实现成绩分布、专业对比等可视化。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
class StudentAnalyzer:
def __init__(self):
self.df = None
self.load_data()
def load_data(self):
if os.path.exists('data/students_data.csv'):
self.df = pd.read_csv('data/students_data.csv')
else:
from data_generator import generate_fake_students
generate_fake_students()
self.df = pd.read_csv('data/students_data.csv')
# 计算总分和平均分
self.df['总分'] = self.df['数学成绩'] + self.df['Python成绩'] + self.df['英语成绩']
self.df['平均分'] = self.df['总分'] / 3
print("学生数据加载成功")
def plot_score_distribution(self, save_path='student_scores.png'):
"""成绩分布直方图"""
plt.figure(figsize=(12, 5))
plt.subplot(1, 3, 1)
self.df['数学成绩'].hist(bins=10, color='red', alpha=0.7)
plt.title('数学成绩分布')
plt.xlabel('分数')
plt.subplot(1, 3, 2)
self.df['Python成绩'].hist(bins=10, color='blue', alpha=0.7)
plt.title('Python成绩分布')
plt.xlabel('分数')
plt.subplot(1, 3, 3)
self.df['英语成绩'].hist(bins=10, color='green', alpha=0.7)
plt.title('英语成绩分布')
plt.xlabel('分数')
plt.suptitle('23级学生各科成绩分布图', fontsize=16)
plt.tight_layout()
plt.savefig(save_path, dpi=100)
plt.close()
return save_path
def plot_major_comparison(self, save_path='student_major.png'):
"""专业成绩对比"""
major_stats = self.df.groupby('专业')['平均分'].mean().sort_values()
plt.figure(figsize=(10, 6))
major_stats.plot(kind='barh', color='teal')
plt.title('各专业学生平均分对比', fontsize=16)
plt.xlabel('平均分')
for i, v in enumerate(major_stats):
plt.text(v + 0.5, i, f'{v:.1f}', va='center')
plt.tight_layout()
plt.savefig(save_path, dpi=100)
plt.close()
return save_path
def plot_gender_analysis(self, save_path='student_gender.png'):
"""性别成绩分析"""
gender_scores = self.df.groupby('性别')[['数学成绩', 'Python成绩', '英语成绩']].mean()
gender_scores.plot(kind='bar', figsize=(10, 6), colormap='Set2')
plt.title('不同性别学生各科平均成绩对比', fontsize=16)
plt.xlabel('性别')
plt.ylabel('平均分')
plt.xticks(rotation=0)
plt.legend(loc='upper right')
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.savefig(save_path, dpi=100)
plt.close()
return save_path
def top_students_table(self, save_path='student_top.png'):
"""优秀学生表格展示 (模拟头像集成)"""
top10 = self.df.nlargest(10, '总分')[['姓名', '专业', 'Python成绩', '总分']]
fig, ax = plt.subplots(figsize=(10, 4))
ax.axis('tight')
ax.axis('off')
table = ax.table(cellText=top10.values, colLabels=top10.columns,
cellLoc='center', loc='center', colColours=['#4472C4']*4)
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1.2, 1.5)
plt.title('23级Python成绩优秀学生榜单 (Top 10)', fontsize=14, pad=20)
plt.savefig(save_path, dpi=100, bbox_inches='tight')
plt.close()
return save_path
if __name__ == '__main__':
sa = StudentAnalyzer()
sa.plot_score_distribution()
sa.plot_major_comparison()
sa.plot_gender_analysis()
sa.top_students_table()
print("学生数据分析图表已生成")
4. 整合 GUI 界面 (main_gui.py)
使用 tkinter 整合所有功能,实现一键分析。
import tkinter as tk
from tkinter import ttk, messagebox
import subprocess
import os
from PIL import Image, ImageTk
import threading
# 导入分析模块
from wechat_analysis import WeChatAnalyzer
from student_analysis import StudentAnalyzer
class DataAnalysisGUI:
def __init__(self, root):
self.root = root
self.root.title("大数据可视化分析系统 - 微信好友 & 23级学生数据")
self.root.geometry("900x650")
self.root.configure(bg='#f0f0f0')
# 设置样式
style = ttk.Style()
style.theme_use('clam')
self.create_widgets()
def create_widgets(self):
# 标题
title_label = tk.Label(self.root, text="📊 数据分析可视化综合平台",
font=("微软雅黑", 20, "bold"), bg='#2c3e50', fg='white')
title_label.pack(fill=tk.X, pady=0, ipady=15)
# 主框架
main_frame = tk.Frame(self.root, bg='#f0f0f0')
main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
# 左侧:微信好友分析模块
wechat_frame = tk.LabelFrame(main_frame, text=" 微信好友数据分析 ",
font=("微软雅黑", 12, "bold"), bg='#f0f0f0', fg='#e74c3c')
wechat_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
btn_style = {"font": ("微软雅黑", 10), "width": 18, "height": 1, "relief": tk.RAISED, "bd": 2}
tk.Button(wechat_frame, text="👥 性别分布可视化", command=self.run_wechat_sex, **btn_style).pack(pady=8)
tk.Button(wechat_frame, text="🗺️ 省份分布可视化", command=self.run_wechat_province, **btn_style).pack(pady=8)
tk.Button(wechat_frame, text="🏙️ 城市分布可视化", command=self.run_wechat_city, **btn_style).pack(pady=8)
tk.Button(wechat_frame, text="⭐ 特殊好友可视化", command=self.run_wechat_special, **btn_style).pack(pady=8)
tk.Button(wechat_frame, text="☁️ 签名词云生成", command=self.run_wechat_wordcloud, **btn_style).pack(pady=8)
# 右侧:学生信息分析模块
student_frame = tk.LabelFrame(main_frame, text=" 23级学生信息分析 ",
font=("微软雅黑", 12, "bold"), bg='#f0f0f0', fg='#3498db')
student_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)
tk.Button(student_frame, text="📈 成绩分布直方图", command=self.run_student_scores, **btn_style).pack(pady=8)
tk.Button(student_frame, text="🎓 专业成绩对比", command=self.run_student_major, **btn_style).pack(pady=8)
tk.Button(student_frame, text="⚧ 性别成绩分析", command=self.run_student_gender, **btn_style).pack(pady=8)
tk.Button(student_frame, text="🏆 优秀学生榜单", command=self.run_student_top, **btn_style).pack(pady=8)
# 底部:全自动分析与打包区域
bottom_frame = tk.Frame(self.root, bg='#f0f0f0')
bottom_frame.pack(fill=tk.X, padx=20, pady=(0, 20))
tk.Button(bottom_frame, text="🚀 一键生成所有报告", command=self.run_all_analysis,
font=("微软雅黑", 12, "bold"), bg='#27ae60', fg='white', height=2).pack(fill=tk.X, pady=5)
# 状态栏
self.status_var = tk.StringVar()
self.status_var.set("就绪 | 共加载 200 条微信数据 & 50 条学生数据")
status_bar = tk.Label(self.root, textvariable=self.status_var, bd=1, relief=tk.SUNKEN, anchor=tk.W)
status_bar.pack(side=tk.BOTTOM, fill=tk.X)
# 初始化数据
self.wc = WeChatAnalyzer()
self.sa = StudentAnalyzer()
def update_status(self, msg):
self.status_var.set(msg)
self.root.update_idletasks()
def show_image(self, path, title="分析结果"):
"""显示生成的图片"""
if os.path.exists(path):
os.startfile(path) # Windows 打开图片
self.update_status(f"已打开: {path}")
else:
messagebox.showerror("错误", f"文件生成失败: {path}")
def run_wechat_sex(self):
self.update_status("正在生成微信性别分布图...")
img = self.wc.plot_sex_distribution()
self.show_image(img)
def run_wechat_province(self):
self.update_status("正在生成省份分布图...")
img = self.wc.plot_province_distribution()
self.show_image(img)
def run_wechat_city(self):
self.update_status("正在生成城市分布图...")
img = self.wc.plot_city_distribution()
self.show_image(img)
def run_wechat_special(self):
self.update_status("正在分析特殊好友...")
img = self.wc.plot_special_friends()
self.show_image(img)
def run_wechat_wordcloud(self):
self.update_status("正在生成词云,请稍等...")
img = self.wc.generate_wordcloud()
self.show_image(img)
def run_student_scores(self):
self.update_status("正在生成成绩分布图...")
img = self.sa.plot_score_distribution()
self.show_image(img)
def run_student_major(self):
self.update_status("正在对比专业成绩...")
img = self.sa.plot_major_comparison()
self.show_image(img)
def run_student_gender(self):
self.update_status("正在分析性别差异...")
img = self.sa.plot_gender_analysis()
self.show_image(img)
def run_student_top(self):
self.update_status("正在生成优秀学生榜单...")
img = self.sa.top_students_table()
self.show_image(img)
def run_all_analysis(self):
"""一键运行所有分析"""
def task():
self.update_status("开始批量生成所有图表...")
self.wc.plot_sex_distribution()
self.wc.plot_province_distribution()
self.wc.plot_city_distribution()
self.wc.plot_special_friends()
self.wc.generate_wordcloud()
self.sa.plot_score_distribution()
self.sa.plot_major_comparison()
self.sa.plot_gender_analysis()
self.sa.top_students_table()
self.update_status("✅ 所有报告生成完毕!共生成9张图表。")
messagebox.showinfo("完成", "所有图表已生成完毕,请查看当前目录!")
threading.Thread(target=task).start()
if __name__ == "__main__":
root = tk.Tk()
app = DataAnalysisGUI(root)
root.mainloop()
第二部分:打包为 EXE 文件 (PyInstaller)
1. 安装 PyInstaller:
pip install pyinstaller
2.执行打包命令:
在项目根目录下打开终端,运行以下命令:
pyinstaller --onefile --windowed --name "数据可视化分析系统" --icon=app.ico main_gui.py
--onefile: 打包成单个 exe 文件。
--windowed: 运行时不显示背后的黑色 CMD 窗口。
--name: 生成的 exe 名称。
打包完成后,在 dist 文件夹中找到 exe 文件,双击即可运行。
四、结果展示
通过运行系统,我们成功生成了以下分析图表:
1. 微信好友性别比例图(男:女 ≈ 4:6)。
2. 微信好友省份热力图(主要集中在河北、黑龙江等)。
3. 23级学生 Python 成绩分布图(主要集中在 75-90 分区间,教学效果良好)。
4. 专业对比柱状图(数据科学专业平均分最高)。
五、总结与未来展望
总结:
本项目成功完成了题目要求的全部功能,实现了从数据清洗、数据分析到可视化呈现的全流程。通过实战,我深入掌握了 pandas 的数据筛选与聚合、matplotlib 的图表定制以及 tkinter 的 GUI 开发。尤其是在处理中文乱码、优化图表美观度方面积累了宝贵经验。
未来展望:
1. 接入真实数据:若微信官方开放接口或利用 mitmproxy 抓包,可接入真实好友数据,使分析更具实际意义。
2. 引入交互式可视化:当前为静态图表,未来可集成 pyecharts 生成动态可交互的 HTML 报告,支持鼠标悬停查看数值。
3. 机器学习预测:利用学生历史成绩数据,构建简单的线性回归模型,预测学生的期末成绩或挂科风险,实现“数据驱动教学”。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)