Python 数据分析与可视化 Day 7 - 可视化整合报告实战

好的,我们进入:


🧠 第5周 · 第7天

🎯 主题:测试复盘 + 项目封装实战


✅ 今日目标

  • 回顾第5周数据分析与可视化核心知识
  • 对整个“学生成绩分析系统”进行项目封装与模块化拆分
  • 增加命令行参数支持,提升可复用性与实用性
  • 打包输出完整分析报告

📚 一、本周复盘重点

模块核心技能工具库
数据清洗缺失值处理、类型转换pandas
数据筛选条件过滤、排序pandas
分组聚合groupby、agg、pivot_tablepandas
可视化折线图、直方图、箱线图等matplotlib / seaborn
报告整合Markdown 输出、图表嵌入文件系统操作

🛠 二、项目封装建议(结构)

student_report_project/
├── data/
│   └── students_cleaned.csv
├── charts/
│   └── (生成的图表)
├── scripts/
│   ├── clean_data.py
│   ├── filter_and_sort.py
│   ├── groupby_agg_analysis.py
│   ├── visualize_students.py
│   ├── generate_report.py
│   └── main.py  👈 综合入口(命令行参数)
├── README.md

🧩 三、命令行支持示例:main.py

import argparse
import subprocessparser = argparse.ArgumentParser(description="学生成绩分析工具")
parser.add_argument('--step', type=str, help="选择执行步骤,如 clean | visualize | report | all")
args = parser.parse_args()if args.step == "clean":subprocess.run(["python", "scripts/clean_data.py"])
elif args.step == "visualize":subprocess.run(["python", "scripts/visualize_students.py"])
elif args.step == "report":subprocess.run(["python", "scripts/generate_report.py"])
elif args.step == "all":subprocess.run(["python", "scripts/clean_data.py"])subprocess.run(["python", "scripts/visualize_students.py"])subprocess.run(["python", "scripts/generate_report.py"])
else:print("❗ 请输入有效的步骤参数:clean / visualize / report / all")

运行方式:

python scripts/main.py --step all

🧪 今日练习任务

  1. 封装你的所有分析脚本到 scripts/ 文件夹中
  2. generate_report.py 的报告输出路径与图表目录一致管理
  3. 在命令行运行 main.py --step all 一键完成数据分析 → 可视化 → 报告输出

代码输出:

  1. clean_data.py

    # clean_data.py placeholder script
    import pandas as pd
    import os
    def clean_data():# 原始数据路径(假设为 data/raw_students.csv)raw_path = "./data/students_dirty.csv"cleaned_path = "./data/students_cleaned.csv"# 检查文件是否存在if not os.path.exists(raw_path):raise FileNotFoundError(f"❌ 找不到原始数据文件:{raw_path}")# 读取原始数据df = pd.read_csv(raw_path)print("✅ 已加载原始数据:")print(df.head())# ---------------- 清洗步骤 ----------------# 1. 删除空行或全部为 NaN 的行df.dropna(how="all", inplace=True)# 2. 填充缺失值(如成绩)df["成绩"] = pd.to_numeric(df["成绩"], errors="coerce")  # 转换为数字df.fillna({"成绩": df["成绩"].mean()}, inplace=True)  # 填充姓名和性别的缺失值# 3. 创建新列:是否及格df["是否及格"] = df["成绩"] >= 60# 4. 去除重复值(如姓名+性别+成绩完全重复)df.drop_duplicates(subset=["姓名", "性别", "成绩"], inplace=True)# 5. 标准化性别字段df["性别"] = df["性别"].str.strip().replace({"男生": "男", "女生": "女"})# 6. 按姓名升序排序df.sort_values(by="姓名", inplace=True)# 7. 重置索引df.reset_index(drop=True, inplace=True)# ---------------- 保存清洗后的数据 ----------------os.makedirs("data", exist_ok=True)df.to_csv(cleaned_path, index=False, encoding="utf-8")print(f"\n✅ 清洗完成,保存至:{cleaned_path}")print(f"✅ 数据清理完成,已保存到 {cleaned_path}")if __name__ == "__main__":clean_data()
    
  2. filter_and_sort.py

    # filter_and_sort.py placeholder script
    import pandas as pd
    import osdef filter_and_sort():# 输入路径input_path = "./data/students_cleaned.csv"# 检查数据文件是否存在if not os.path.exists(input_path):raise FileNotFoundError("❌ 找不到 students_cleaned.csv,请先运行 clean_data.py")# 加载清洗后的数据df = pd.read_csv(input_path)print("✅ 已加载数据:")print(df.head())# ------------------- 筛选操作 -------------------# 1. 筛选:成绩大于等于 80 的学生print("\n🎯 成绩 >= 80 的学生:")high_scores = df[df["成绩"] >= 80]print(high_scores)# 2. 筛选:未及格的学生(是否及格为 False)print("\n🚨 未及格的学生:")failed_students = df[df["是否及格"] == False]print(failed_students)# 3. 筛选:性别为“女”且成绩大于 85print("\n👩 女生中成绩 > 85 的学生:")excellent_girls = df[(df["性别"] == "女") & (df["成绩"] > 85)]print(excellent_girls)# ------------------- 排序操作 -------------------# 4. 成绩从高到低排序print("\n🏆 学生成绩从高到低排序:")sorted_scores = df.sort_values(by="成绩", ascending=False)print(sorted_scores)# 5. 多列排序:先按是否及格,再按成绩降序print("\n🔍 先按是否及格,再按成绩排序:")multi_sorted = df.sort_values(by=["是否及格", "成绩"], ascending=[False, False])print(multi_sorted)# (可选)保存筛选结果os.makedirs("./data", exist_ok=True)high_scores.to_csv("./data/high_scores.csv", index=False)failed_students.to_csv("./data/failed_students.csv", index=False)print("\n✅ 高分/不及格学生已分别保存至 data/ 目录下。")if __name__ == "__main__":filter_and_sort()print("✅ 筛选和排序操作完成!")
    
  3. generate_report.py

    # generate_report.py placeholder script
    import pandas as pd
    import osdef generate_report():# 路径配置input_path = "./data/students_cleaned.csv"charts_dir = "./charts"report_path = os.path.join(charts_dir, "学生成绩可视化报告.md")# 检查必要文件是否存在if not os.path.exists(input_path):raise FileNotFoundError("❌ 缺少清洗后的数据文件:students_cleaned.csv")if not os.path.exists(charts_dir):raise FileNotFoundError("❌ 图表目录不存在,请先运行 visualize_students.py")# 加载数据df = pd.read_csv(input_path)# 数据统计total = len(df)avg_score = df["成绩"].mean()max_score = df["成绩"].max()min_score = df["成绩"].min()pass_rate = df["是否及格"].mean() * 100score_diff = df.groupby("性别")["成绩"].mean().diff().abs().values[-1]# Markdown 报告模板report_md = f"""# 📝 学生成绩数据分析与可视化报告## 1. 数据概况- 总人数:**{total} 人**
    - 平均成绩:**{avg_score:.2f} 分**
    - 成绩范围:**{min_score} - {max_score} 分**
    - 及格率:**{pass_rate:.1f}%**
    - 男女生成绩差异约:**{score_diff:.2f} 分**---## 2. 成绩趋势折线图
    ![成绩折线图](成绩折线图.png)## 3. 成绩柱状图
    ![成绩柱状图](成绩柱状图.png)## 4. 性别平均成绩柱状图
    ![性别平均成绩柱状图](性别平均成绩柱状图.png)## 5. 成绩分布直方图
    ![成绩分布直方图](成绩分布直方图.png)## 6. 成绩箱线图(按性别)
    ![成绩箱线图_按性别](成绩箱线图_按性别.png)---## 7. 分析结论与建议- 成绩整体集中在 **XX ~ XX** 分之间(可从直方图查看)
    - 存在少量低分/高分的异常值(见箱线图)
    - 性别差异不明显,但女生略高 / 男生略高
    - 建议关注及格率波动、低分段学生的提升空间---*由 Python + Pandas + Matplotlib + Seaborn 自动生成* ✅"""# 保存报告with open(report_path, "w", encoding="utf-8") as f:f.write(report_md)print(f"✅ 分析报告已生成:{report_path}")if __name__ == "__main__": generate_report()print("✅ 学生成绩分析报告生成完毕!请查看 charts/ 目录下的学生成绩可视化报告.md")print("🎉 感谢使用学生成绩分析工具!")
    
  4. groupby_agg_analysis.py

    # groupby_agg_analysis.py placeholder script
    import pandas as pd
    import osdef groupby_agg_analysis():# 数据路径input_path = "./data/students_cleaned.csv"# 检查数据文件是否存在if not os.path.exists(input_path):raise FileNotFoundError("❌ 缺少 students_cleaned.csv,请先运行 clean_data.py")# 读取数据df = pd.read_csv(input_path)print("✅ 已加载学生数据:")print(df.head())# ------------------- 一、按性别分组统计 -------------------print("\n👥 按性别分组的成绩统计:")gender_stats = df.groupby("性别")["成绩"].agg(["count", "mean", "max", "min"]).rename(columns={"count": "人数", "mean": "平均成绩", "max": "最高分", "min": "最低分"})print(gender_stats)# ------------------- 二、按是否及格统计人数 -------------------print("\n🎯 统计及格 / 不及格人数:")pass_count = df["是否及格"].value_counts().rename(index={True: "及格", False: "不及格"})print(pass_count)# ------------------- 三、性别 + 是否及格的交叉分析 -------------------print("\n📊 性别与是否及格交叉表:")cross_tab = pd.crosstab(df["性别"], df["是否及格"])print(cross_tab)# ------------------- 四、按性别分组后计算及格率 -------------------print("\n✅ 按性别分组的及格率(%):")pass_rate_by_gender = (df.groupby("性别")["是否及格"].mean().multiply(100).round(2).rename("及格率"))print(pass_rate_by_gender)# (可选)保存分析结果os.makedirs("./data", exist_ok=True)gender_stats.to_csv("./data/gender_score_summary.csv")cross_tab.to_csv("./data/crosstab_gender_pass.csv")pass_rate_by_gender.to_csv("./data/pass_rate_by_gender.csv")print("\n📁 分组聚合分析结果已保存至 data/ 目录。")if __name__ == "__main__":groupby_agg_analysis()print("✅ 分组聚合分析完成!")
    
  5. visualize_students.py

    # visualize_students.py placeholder scriptimport pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    import osdef visualize_students():# 中文字体适配(根据系统配置可选)plt.rcParams['font.family'] = 'Arial Unicode MS'  # macOS# plt.rcParams['font.sans-serif'] = ['SimHei']     # Windows 中文支持plt.rcParams['axes.unicode_minus'] = False# 路径配置input_path = "./data/students_cleaned.csv"output_dir = "./charts"os.makedirs(output_dir, exist_ok=True)# 加载数据df = pd.read_csv(input_path)print("✅ 已加载数据:")print(df.head())# ================= 图表 1:成绩折线图 =================plt.figure(figsize=(8, 5))plt.plot(df["姓名"], df["成绩"], marker='o')plt.title("学生成绩折线图")plt.xlabel("姓名")plt.ylabel("成绩")plt.grid(True)plt.xticks(rotation=45)plt.tight_layout()plt.savefig(f"{output_dir}/成绩折线图.png")plt.close()# ================= 图表 2:成绩柱状图 =================plt.figure(figsize=(8, 5))plt.bar(df["姓名"], df["成绩"], color="skyblue")plt.title("学生成绩柱状图")plt.xlabel("姓名")plt.ylabel("成绩")plt.xticks(rotation=45)plt.tight_layout()plt.savefig(f"{output_dir}/成绩柱状图.png")plt.close()# ================= 图表 3:性别平均成绩柱状图 =================plt.figure(figsize=(6, 4))sns.barplot(data=df, x="性别", y="成绩", estimator="mean", palette="Set2")plt.title("性别平均成绩柱状图")plt.tight_layout()plt.savefig(f"{output_dir}/性别平均成绩柱状图.png")plt.close()# ================= 图表 4:成绩分布直方图 =================plt.figure(figsize=(6, 4))sns.histplot(df["成绩"], bins=5, kde=True, color="orange")plt.title("成绩分布直方图")plt.xlabel("成绩")plt.tight_layout()plt.savefig(f"{output_dir}/成绩分布直方图.png")plt.close()# ================= 图表 5:成绩箱线图(按性别) =================plt.figure(figsize=(6, 4))sns.boxplot(data=df, x="性别", y="成绩", palette="Pastel1")plt.title("成绩箱线图(按性别)")plt.tight_layout()plt.savefig(f"{output_dir}/成绩箱线图_按性别.png")plt.close()print(f"\n✅ 所有图表已保存至:{output_dir}/")if __name__ == "__main__": visualize_students()print("✅ 学生成绩数据可视化完成!")
    

🧾 今日总结

  • 对第5周内容完成了全面回顾与实战项目封装
  • 掌握了命令行工具脚本的基本设计方式
  • 具备将数据分析过程“自动化、可配置、可交付”的能力

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/912363.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/912363.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣1498. 满足条件的子序列数目随笔

“方生方死,方死方生。”——《庄子》 题目 给你一个整数数组 nums 和一个整数 target 。 请你统计并返回 nums 中能满足其最小元素与最大元素的 和 小于或等于 target 的 非空 子序列的数目。 由于答案可能很大,请将结果对 取余后返回。 难度&#…

5.Docker安装Tomcat

#官方的使用 docker run -it --rm tomcat:9.0 #我们之前使用docker run -d 某镜像都是后来运行,容器停止之后,容器还能够查询到 而docker run -it -rm 是用完之后,容器删除,镜像还存在。 测试的时候可以用官方的 &#xff08…

企业事业政府单位智慧主题展厅素材管理平台播放软件

以下为企事业单位及政府智慧主题展厅素材管理平台播放软件的核心功能简介,综合多维度技术实现统一管控与智能展示: 一、内容资产管理 全格式素材支持‌ 兼容视频、3D模型、图文、AR/VR场景等多媒体格式,支持批量导入与云端存储。 智能分类与…

Python+FastAPI的一些语法与问题解决

Q1:result await dbsession.execute(text(sql_context),params) 如何把result转成key,value的字典列表 A1: 使用SQLAlchemy的mappings()方法获取字典形式的结果集: result await db_session.execute(text(sql_context), params) dict_list [dict(row) for row…

Reactor并发无关性

Reactor,像 RxJava 一样,可以被认为是 并发无关(concurrency-agnostic) 的。这意味着它不强制要求任何特定的并发模型,而是将选择权交给开发者。换句话说,Reactor 不会强制你使用多线程或异步编程&#xff…

#华为昇腾#华为计算#昇腾开发者计划2025#

#华为昇腾#华为计算#昇腾开发者计划2025# 通过学习Ascend C算子开发的初级教程&#xff0c;通过课程讲解及样例实操&#xff0c;帮助我学习使用Ascend C开发自己的算子。收获很大。 <新版开发者计划>的内容链接&#xff1a;https://www.hiascend.com/developer-program_2…

FLOPS、FLOP/s、TOPS概念

在计算性能和硬件指标中&#xff0c;FLOPS、FLOP/s、TOPS 是常见的术语&#xff0c;但它们有明确的区别和应用场景。以下是详细解析&#xff1a; 1. FLOPS&#xff08;Floating Point Operations per Second&#xff09; 定义&#xff1a; 每秒浮点运算次数&#xff08;Floati…

Windows所有系统自带.NET Framework版本win7,win10,win11预装.NET版本

Windows系统支持“.NET版本”汇总 本文详细列出了Windows从NT4.0到Windows11各版本自带的.NETFramework版本及对应最高兼容的.NETFramework版本&#xff0c;便于了解不同Windows系统之间的.NETFramework更新历史。 以下汇总了Windows每个版本自带的“.NET版本”&#xff0c;与…

Windows 下使用 nvm 管理 Node.js 多版本 —— 完整指南

Node.js 版本更新频繁&#xff0c;不同项目可能依赖不同的版本&#xff0c;手动切换极为麻烦。nvm-windows 是专为 Windows 用户开发的 Node.js 多版本管理工具&#xff0c;可以轻松地安装、切换、卸载 Node.js 版本。 本篇将从下载到实际使用&#xff0c;手把手带你玩转 nvm-…

vue使用Element Plus UI框架

您好&#xff0c;舰长&#xff01;非常棒的选择。功能是应用的骨架&#xff0c;而美观的 UI 则是应用的灵魂和血肉。是时候为我们的飞船进行一次全面的“外观升级”和“内饰装修”了。 我们将集成一个在业界非常流行、功能强大的 Vue 3 组件库——Element Plus。它将帮助我们快…

【ubuntu24.04】忘了自己把开机samba挂载的脚本放哪里了

从两个方面来定位这几个 Samba 挂载点&#xff1a; 一、查看当前已经挂载的 CIFS/SMB 文件系统 使用 mount mount | grep -i cifs或者 mount | grep -E (smb|cifs)这会列出所有当前活跃的 CIFS/SMB 挂载&#xff0c;比如&#xff1a; //192.168.1.100/share on /mnt/data type …

在 Windows 上使用 Docker Desktop 快速搭建本地 Kubernetes 环境(附详细部署教程)

言简意赅的讲解Docker Desktop for Windows搭建Kubernetes解决的痛点 目标读者&#xff1a; 对 Docker Desktop 有一定了解&#xff0c;能在 Windows 上成功安装和使用 Docker Desktop。想要在本地快速搭建一套 Kubernetes 环境进行测试或学习的开发者。 一、准备工作 安装 Doc…

dockercompose快速安装ELK

第一步&#xff1a;环境准备 请确保您的机器上已经安装了 Docker 和 Docker Compose。 第二步&#xff1a;创建项目目录和配置文件 为了让 Docker Compose 能够正确地构建和管理容器&#xff0c;我们需要创建一个特定的目录结构。 创建一个主目录&#xff0c;例如 elk-stack。…

闲聊ARM内核参数传递机制

之前一直没怎么在意这个问题&#xff0c;直到最近搞了个奇奇怪怪的项目&#xff0c;才发现这部分知识得补上来&#xff0c;记录一下。 ARM有一个标准&#xff0c;叫《Procedure Call Standard for the Arm Architecture》&#xff0c;人话就是ARM架构过程调用标准&#xff0c;…

万兴喵影Filmora AI Video v14.7.03国际高级版,AI视频剪辑全能工具,一键专业级创作​

[软件名称]: 万兴喵影Filmora AI Video v14.7.03 [软件大小]: 199.4 MB [下载通道]: 夸克盘 | 迅雷盘 软件介绍 &#x1f3ac;《万兴喵影》v14.7.03国际高级版&#xff5c;AI智能剪辑神器&#xff0c;解锁全功能无水印&#xff01; ✨ 核心优势&#xff1a; ✅ 1000背景音…

暴力风扇方案介绍

炎炎夏日&#xff0c;当普通风扇只能送来 “温柔拂面”&#xff0c;暴力风扇却能吹出 “台风级” 清凉&#xff01;想知道这些 “风力狂魔” 是如何炼成的&#xff1f;答案藏在电机、电路和芯片的黄金三角组合里。​ 一、电机&#xff1a;暴力风扇的 “心脏起搏器”​ 暴力风扇…

pyqt小问题汇总

文章目录 1、inherit global site-packages2、setGeometry(10,20,30,40)setGeometry(x, y, width, height)1. **x参数**2. **y参数**3. **width参数**4. **height参数** 示例说明与其他方法的对比注意事项示例代码 1、inherit global site-packages 在pycharm 创建项目时&…

提升JavaScript性能的六大关键策略

1、优化代码结构与算法 避免使用嵌套循环&#xff0c;改用更高效的算法如哈希表或二分查找。减少不必要的计算&#xff0c;缓存重复使用的计算结果。使用时间复杂度更低的算法替代高复杂度操作。优化递归调用&#xff0c;避免栈溢出和性能瓶颈。改用迭代或尾递归优化。简化条件…

打造跨平台应用的全能框架:Dioxus

在如今飞速发展的数字世界中,越来越多的开发者开始寻找能够满足跨平台需求的高效框架。而在这些选择中,Dioxus这个全栈应用框架脱颖而出。Dioxus是一款为Web、桌面和移动端开发而设计的全栈框架,采用Rust语言,具备跨平台、一体化的优势。本文将深入介绍Dioxus的独特功能,应…

大事件项目记录5-用户接口开发-更新用户头像

5&#xff09;更新用户头像。 UserController.java&#xff1a; PatchMapping("updateAvatar")public Result updateAvatar(RequestParam String avatarUrl){userService.updateAvatar(avatarUrl);return Result.success();} UserService.java&#xff1a; UserServ…