新高考 “七选三” 选科直接影响学生高考志愿、专业选择甚至未来职业方向。传统凭感觉选科容易出现学科不匹配、成绩波动大、竞争劣势等问题。
本文基于
Python+Pandas+Matplotlib+Seaborn + 机器学习,对某高中高二学生脱敏成绩数据进行全流程选科数据分析,包含:
全程保姆级步骤,小白可直接运行,适合高中生、家长、老师、数据爱好者学习!
目录
5.数据清洗(核心!无效成绩 + 异常值 + 去重)9.数据可视化分析10.进阶:机器学习清洗 + 特征工程1️⃣ 项目背景与数据说明
1.1 业务背景
新高考 “七选三”:物理、化学、生物、历史、地理、政治、技术,学生必须从中选择 3 门作为高考选考科目。
选科直接决定:
目标:用数据科学给出最科学的选科建议,而不是凭兴趣、跟风、凭感觉选科。
1.2 数据集说明
- 脱敏处理:删除姓名、身份证、家庭信息,仅保留学号、班级、科目、考试、成绩
- 数据规模:2000+ 学生,7 门选考科目,多学期考试成绩
数据集链接:https://pan.baidu.com/s/13kFfJU_4fL8PvW-VtDQ8rA提取码可私信获取
2️⃣ 技术栈选型
- Matplotlib / Seaborn:数据可视化绘图
3️⃣ 环境准备
安装依赖库:
pip install pandas numpy matplotlib seaborn scikit-learn
4️⃣ 数据获取与筛选(高二专属)
由于只有高二学生需要选科,因此第一步必须精准筛选,剔除高一、高三数据,保证分析精准。
4.1 读取学生信息
student_info = pd.read_csv("../data/2_student_info.csv")gaoer_student = student_info[student_info["cla_Name"].str.contains("高二", na=False)]gaoer_ids = gaoer_student["bf_StudentID"].tolist()
df = pd.read_csv('../data/5_chengji.csv')df = df[df["mes_StudentID"].isin(gaoer_ids)]
5️⃣ 数据清洗(核心)
原始成绩数据非常脏,必须清洗:
5.1 筛选七选三科目
SUBJECT_LIST = ['物理','化学','生物','历史','地理','政治','技术']df = df[df['mes_sub_name'].isin(SUBJECT_LIST)].copy()
df['mes_Score'] = pd.to_numeric(df['mes_Score'], errors='coerce')df = df[(df['mes_Score'] > 0) & (~df['mes_Score'].isin([-1, -2, -3]))].copy()
df['mes_Score'] = df['mes_Score'].fillna(df.groupby('mes_sub_name')['mes_Score'].transform('mean'))df = df.dropna(subset=['mes_Score'])
6️⃣ Z 分数标准化计算
不同科目、不同考试难度不同,不能直接用原始分比较强弱。必须使用 Z 分数 实现跨科目公平对比。
公式:Z = (个人成绩 - 科目平均分) / 科目标准差
defcalculate_z_by_exam(group): scores = group['mes_Score'] std = scores.std() group['mes_Z_Score'] = (scores - scores.mean()) / std if std != 0else0 return groupdf = df.groupby(['mes_TestID','mes_sub_name']).apply(calculate_z_by_exam)
作用:
7️⃣ 选科状态识别(已定科 / 待选科)
根据学生有效成绩科目数,自动划分学生类型:
defis_fixed(row): returnsum(1for sub in SUBJECT_LIST if row[sub] != 0) == 3fixed_stu = pivot[pivot.apply(is_fixed, axis=1)]free_stu = pivot[~pivot.apply(is_fixed, axis=1)]
8️⃣ 选科推荐算法(综合评分模型)
本项目采用多维度加权综合评分,比单纯看分数更科学、更贴合高中实际。
评分公式:
df["选科综合得分"] = ( df["Z得分"] * 0.4 + df["原始分得分"] * 0.3 + df["稳定性得分"] * 0.2 + df["区分度得分"] * 0.1)
按综合得分排序,自动取前三科作为推荐结果。
同时输出两套方案:
9️⃣ 数据可视化分析
9.1 科目难度箱线图
直观展示各科难度、平均分、分数分布:
sns.boxplot(data=score_pivot, palette='Set2')plt.axhline(年级均值, color='red', linestyle='--')plt.savefig('科目难度箱线图.png')

9.2 学科相关性热力图
展示科目之间关联性,帮助选择学习效率更高的组合:
corr_matrix = score_pivot.corr()sns.heatmap(corr_matrix, annot=True, cmap='coolwarm')plt.savefig('学科相关性热力图.png')

🔟 进阶:机器学习清洗 + 特征工程
10.1 孤立森林异常检测
自动识别异常成绩,比人工规则更智能:
iso_forest = IsolationForest(contamination=0.05)df['anomaly'] = iso_forest.fit_predict(df[['mes_Score']])df = df[df['anomaly'] == 1]
10.2 特征工程:成绩稳定性
计算变异系数 CV,识别 “高分不稳” 的学生:
student_features['cv'] = student_features['score_std'] / student_features['score_mean']
1️⃣1️⃣ 项目运行效果
运行后自动输出 6 个文件:
最终推荐表包含:
学生选课推荐表
mes_StudentID | 最优选科组合 | 最优评分 | 备选选科组合 | 备选评分 |
11048 | 化学+生物+物理 | 0.19 | 化学+物理+生物 | 0.19 |
11249 | 化学+生物+历史 | 0.19 | 技术+生物+地理 | 0.06 |
11352 | 地理+政治+物理 | 1.0 | 地理+历史+生物 | 0.55 |
已定科学生分析表
mes_StudentID | 已选科目组合 | 平均关联度 | 关联标签 |
10842 | 物理 + 政治 + 技术 | 0.3 | 低关联 |
10843 | 物理 + 政治 + 技术 | 0.3 | 低关联 |
10844 | 物理 + 政治 + 技术 | 0.3 | 低关联 |
10845 | 物理 + 政治 + 技术 | 0.3 | 低关联 |
10846 | 化学 + 生物 + 地理 | 0.57 | 高关联 |
1️⃣2️⃣ 踩坑总结
1️⃣3️⃣ 项目优化方向