Python 实战 | 班级学风精准画像:从考勤成绩数据看透班风,量化评价有凭有据
大家好~本篇带来校园数据治理实战——基于 Python 对全校班级学风做自动化、可视化、可落地的综合分析。
前言:
在校园管理中,班级学风评价往往依赖经验判断,不够客观也难以量化。 本文用真实业务数据(学生档案、考勤、考试、成绩),通过 Pandas 清洗分析 + Matplotlib 可视化, 全自动生成学风评分、班风等级、对比图表,让学风评价公平、直观、有数据支撑!
全文侧重实战流程、清洗逻辑、可视化展示,小白也能直接跑通、直接复用~
目录
一、项目背景与核心目标
二、数据源说明
三、技术栈选型
四、核心分析思路
五、代码分步实现
5.1、 环境配置与路径设置
5.2、 数据读取与初步处理
5.3、数据清洗与班级聚合
5.4、 关键指标计算函数
5.5、学风综合得分公式
5.6、等级划分标准
5.7、可视化图表生成
六、可视化结果展示
1. 班级学风综合得分排行榜
2. 班级平均分对比
3. 班级出勤率对比
4. 班级违纪率分布
5.班级缺考率分布
6. 班级学风等级分布饼图
📌 七、分析结论与管理建议
🎯 八、实战总结
一、项目背景与核心目标
传统班级学风评价依赖班主任主观打分,缺乏统一标准,可比性差。通过数据化分析,可以:
- 客观衡量班级纪律、成绩、学风差异
- 快速定位优秀班级与待改进班级
- 生成可视化图表用于汇报、评比、管理
- 让学风评价从 “凭感觉” 变成 “看数据”
本次目标:基于学生考勤、考试、成绩数据,构建班级学风综合评分体系,实现全自动化分析与图表输出。
二、数据源说明
本次使用4类清洗过后的学校核心业务 CSV 数据:
| 文件名 | 数据说明 | 用途 |
| clean_student_profile.csv | 学生综合画像表 | 整合学生基础信息、平均成绩、有效考勤等数据,是本次班级学风分析的主数据源。 |
| clean_attendance.csv | 考勤数据表 | 记录学生出勤、迟到、早退等行为,用于计算出勤率与班级纪律表现。 |
| clean_score.csv | 成绩数据表 | 存储学生历次考试成绩,用于计算平均分与班级学业水平。 |
| clean_exam_type.csv | 考试类型表 | 用于筛选有效正式考试,保证成绩可信,用于计算缺考率与考试参与度。 |
关键字段:
- 学生 ID、班级
- avg_score:平均成绩
- attendance_event_count:考勤总记录
- late_count /early_leave_count:迟到、早退次数
- valid_exam_count:有效考试次数
- absent_exam_count:缺考次数
数据覆盖多班级,无敏感信息,是非常经典的校园数据分析实战场景。
三、技术栈选型
- Python 3.x
- Pandas:数据读取、分组聚合、指标计算
- Matplotlib:可视化绘图(横向柱状图、饼图)
- OS:文件路径、输出管理
轻量化、易部署、可直接用于课程设计与实战项目。
四、核心分析思路
本次分析严格围绕学风四大真实维度:
- 学业水平:班级平均分、及格率、优秀率
- 出勤纪律:出勤率、迟到率
- 考试态度:缺考率
- 成绩稳定性:成绩标准差→稳定性得分
最终加权得到学风综合得分,并划分等级:
- 80 分以上:优秀
- 75~79 分:良好
- 65~74 分:一般
- 65 分以下:待改进
五、代码分步实现
5.1、 环境配置与路径设置
import pandas as pd import numpy as np import matplotlib.pyplot as plt import os import warnings warnings.filterwarnings('ignore') # 路径配置 BASE_PATH = r"C:\商业数据分析\JupyterProject\outputs\cleaned" OUTPUT_PATH = r"C:\商业数据分析\JupyterProject\outputs\学风分析" os.makedirs(OUTPUT_PATH, exist_ok=True)5.2、 数据读取与初步处理
# 读取数据源 df_profile = pd.read_csv(os.path.join(BASE_PATH, "clean_student_profile.csv")) df_attendance = pd.read_csv(os.path.join(BASE_PATH, "clean_attendance.csv")) df_score = pd.read_csv(os.path.join(BASE_PATH, "clean_score.csv")) df_exam = pd.read_csv(os.path.join(BASE_PATH, "clean_exam_type.csv")) # 过滤无效班级 df_profile = df_profile[~df_profile["cla_Name"].str.contains("未分班", na=False)] df_attendance = df_attendance[~df_attendance["cla_Name"].str.contains("未分班", na=False)] # 过滤班级名称为空的数据 df_profile = df_profile[df_profile["cla_Name"].notna()] df_attendance = df_attendance[df_attendance["cla_Name"].notna()]5.3、数据清洗与班级聚合
attendance_summary = df_attendance # 学生数据聚合(班级人数、成绩、考试) class_academic = df_profile.groupby("cla_Name").agg( 班级人数=("bf_StudentID", "nunique"), 有效考试次数=("valid_exam_count", lambda x: x.fillna(0).sum()), 缺考次数=("absent_exam_count", lambda x: x.fillna(0).sum()), 班级平均分=("avg_score", lambda x: x.fillna(0).mean()), 成绩标准差=("avg_score", lambda x: x.fillna(0).std()), ).reset_index() # 合并考勤数据 + 学业数据 class_report = pd.merge(attendance_summary, class_academic, on="cla_Name", how="inner")5.4、 关键指标计算函数
# 1. 出勤率计算 class_report["出勤率(%)"] = round((class_report["缺勤"] / class_report["总记录数"]) * 100, 2) # 2. 违纪率计算 class_report["违纪率(%)"] = round( (class_report["早退"] + class_report["迟到"] + class_report["校服不合规"]) / class_report["总记录数"] * 100, 2 ) # 3. 缺考率计算 class_report["缺考率(%)"] = class_report.apply( lambda x: round((x["缺考次数"] / (x["有效考试次数"] + x["缺考次数"])) * 100, 2) if (x["有效考试次数"] + x["缺考次数"]) > 0 else np.nan, axis=1 )5.5、学风综合得分公式
def calc_score(row): attend = row["出勤率(%)"] if pd.notna(row["出勤率(%)"]) else 70 discipline = 100 - row["违纪率(%)"] if pd.notna(row["违纪率(%)"]) else 70 exam = 100 - row["缺考率(%)"] if pd.notna(row["缺考率(%)"]) else 75 score = row["班级平均分"] if row["班级平均分"] > 0 else 60 stable = np.clip(100 - row["成绩标准差"], 60, 100) total = (attend * 0.125) + (discipline * 0.125) + (exam * 0.15) + (score * 0.4) + (stable * 0.2) return np.clip(round(total + 8, 2), 40, 100) class_report["学风综合得分"] = class_report.apply(calc_score, axis=1)5.6、等级划分标准
def get_level(s): if s >= 80: return "优秀" elif s >= 75: return "良好" elif s >= 65: return "一般" else: return "待改进" class_report["学风等级"] = class_report["学风综合得分"].apply(get_level)5.7、可视化图表生成
color_map = {'优秀': '#2ECC71', '良好': '#3498DB', '一般': '#F1C40F', '待改进': '#E74C3C'} # 1. 学风综合得分排行 score_data = class_report.sort_values("学风综合得分", ascending=False) plt.figure(figsize=(13,9)) plt.barh(score_data["cla_Name"][::-1], score_data["学风综合得分"][::-1], color=[color_map[x] for x in score_data["学风等级"][::-1]]) plt.title("各班级学风综合得分排行榜") plt.xlabel("学风综合得分") plt.grid(alpha=0.3) plt.tight_layout() plt.savefig(f"{OUTPUT_PATH}/01_学风排行.png", dpi=200) plt.close() # 2. 班级平均分对比 avg_data = class_report[class_report["班级平均分"]>0].sort_values("班级平均分", ascending=False) plt.figure(figsize=(13,9)) plt.barh(avg_data["cla_Name"][::-1], avg_data["班级平均分"][::-1], color="#4CC9F0") plt.title("各班级平均分对比") plt.xlabel("班级平均分") plt.tight_layout() plt.savefig(f"{OUTPUT_PATH}/02_班级平均分.png", dpi=200) plt.close() # 3. 出勤率对比 attend_data = class_report.sort_values("出勤率(%)", ascending=False) plt.figure(figsize=(13,9)) plt.barh(attend_data["cla_Name"][::-1], attend_data["出勤率(%)"][::-1], color="#27AE60") plt.title("各班级出勤率对比") plt.xlabel("出勤率(%)") plt.xlim(0,100) plt.grid(alpha=0.3) plt.tight_layout() plt.savefig(f"{OUTPUT_PATH}/03_班级出勤率.png", dpi=200) plt.close() # 4. 违纪率对比 disci_data = class_report.sort_values("违纪率(%)", ascending=True) plt.figure(figsize=(13,9)) plt.barh(disci_data["cla_Name"][::-1], disci_data["违纪率(%)"][::-1], color="#E74C3C") plt.title("各班级违纪率对比") plt.xlabel("违纪率(%)") plt.xlim(0,100) plt.grid(alpha=0.3) plt.tight_layout() plt.savefig(f"{OUTPUT_PATH}/04_班级违纪率.png", dpi=200) plt.close() # 5. 缺考率对比 absent_data = class_report.sort_values("缺考率(%)", ascending=True) plt.figure(figsize=(13,9)) plt.barh(absent_data["cla_Name"][::-1], absent_data["缺考率(%)"][::-1], color="#E67E22") plt.title("各班级缺考率") plt.xlabel("缺考率(%)") plt.xlim(0,30) plt.grid(alpha=0.3) plt.tight_layout() plt.savefig(f"{OUTPUT_PATH}/05_班级缺考率.png", dpi=200) plt.close() # 6. 学风等级饼图 lev = class_report["学风等级"].value_counts() plt.figure(figsize=(7,7)) plt.pie(lev, labels=lev.index, autopct="%1.1f%%", colors=[color_map[i] for i in lev.index]) plt.title("班级学风等级分布") plt.tight_layout() plt.savefig(f"{OUTPUT_PATH}/06_学风等级饼图.png", dpi=200) plt.close()技术要点说明
- 使用Pandas的groupby+agg实现多维度聚合
- 通过lambda函数处理缺失值
- 自定义评分公式反映真实业务逻辑
- 可视化采用横向柱状图清晰展示排名
- 结果输出同时包含CSV和图片格式
六、可视化结果展示
1. 班级学风综合得分排行榜
2. 班级平均分对比
3. 班级出勤率对比
4. 班级违纪率分布
5.班级缺考率分布
6. 班级学风等级分布饼图
📌 七、分析结论与管理建议
- 全校班级学风整体呈正态分布,良好 / 一般占主体,结构健康。
- 平均分与出勤率呈明显正相关,课堂纪律直接影响学业表现。
- 低缺考率班级普遍学风更优秀,考试态度是关键信号。
- 少数班级纪律薄弱、出勤率偏低,可重点加强考勤管理。
建议:
- 优秀班级:固化经验,全校推广
- 良好班级:提升弱势学科
- 一般班级:强化课堂纪律
- 待改进班级:开展班风整顿与学习习惯培养
🎯 八、实战总结
本次实战完整实现了校园班级学风数据化评价体系,从数据读取、清洗、聚合、指标计算到可视化输出全流程自动化。
亮点:
- 指标体系科学、贴合校园管理逻辑
- 图表清晰、直观、可直接用于汇报
- 代码模块化、易修改、可复用
- 不依赖主观打分,全部用数据说话
无论是课程作业还是校园真实管理,这套方法都能直接落地~
