用python预测高考成绩

感谢 @ButtersPC 提供的数据集。

本文旨在学习数据分析的基本过程,文中敏感数据均已隐藏。本文通过一些基本描述统计,如考生人数、科目分数及平均分、考试排名,文科理科等因素,尽可能地探求数据集中包含的有价值的信息,来预测高考成绩。

导读:

1、数据集选用“某年上海某区高考二模成绩”

2、上海过去几年的高考制度采用“3+1+1”的模式,语数英 + 加一学科 + 综合,加一学科指在物理、化学、生物、地理、政治、历史中选其一。(这条信息很重要,有助于帮我们理解数据)

使用工具

pandas、numpy

matplotlib 数据可视化

Jupyter Notebook 数据分析利器

一、导入数据

# 导包
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签
# plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号

import pandas as pd
import numpy as np
# 导入数据
filename = './**.xls'

# df_w 文科生原始数据
# df_l 理科生原始数据
df_w = pd.read_excel(filename, sheet_name=0)
df_l = pd.read_excel(filename, sheet_name=1)
# 查看文科生数据
print(df_w.columns)
df_w.head(3)
Index(['学科', '学校', '准考证号', '姓名', '语文', '数学', '英语', '五门调整总分', '总分排名'], dtype='object')

《用python预测高考成绩》
《用python预测高考成绩》

# 查看理科生数据
print(df_l.columns)
df_l.head(3)
Index(['学科', '学校', '准考证号', '姓名', '语文', '数学', '英语', '加一调整分', '五门总分', '总分排名'], dtype='object')

《用python预测高考成绩》
《用python预测高考成绩》

# 查看数据格式
# 是否需要转换
df_l.dtypes
学科        object
学校        object
准考证号       int64
姓名        object
语文       float64
数学       float64
英语       float64
加一调整分      int64
五门总分     float64
总分排名       int64
dtype: object
df_w.dtypes
学科         object
学校         object
准考证号        int64
姓名         object
语文        float64
数学        float64
英语        float64
五门调整总分    float64
总分排名        int64
dtype: object

从上面发现数据质量很高,非常工整。但也存在几个小问题。

1、文科生没有“加一调整分”列

2、文科生“五门调整总分”同 文科生“五门总分”列名不相同。

二、数据处理

# 修改文科生列名
df_w = df_w.rename(columns = {'五门调整总分':'五门总分'})
df_w.head()

《用python预测高考成绩》
《用python预测高考成绩》

# 合并文科和理科学生数据
df_new = pd.concat([df_w, df_l], ignore_index=True)

# 调整列的顺序,使看起来更顺眼
columns = ['学科','学校','准考证号','姓名','语文','数学','英语','加一调整分','五门总分','总分排名']
df_new = pd.DataFrame(df_new, columns=columns)

# 在“五门总分”前插入新的一列“三门总分”
sanmen = df_new['语文'] + df_new['数学'] + df_new['英语']
df_new.insert(8,'三门总分',sanmen) 

df_new.head()

《用python预测高考成绩》
《用python预测高考成绩》

简单数据处理后,我们把文科生成绩和理科生成绩的两张数据表合并了,由于文科生数据表中没有“加一调整分”一列,因此所有文科生的该列为空(NaN),然后我们可以进入进一步挖掘了。

三、数据分析

经过之前的数据处理,现在我们可以对数据集进行基础的描述性统计分析。

# 分析数据 这里只对文科学生分析

#获取描述统计信息
df_w.describe()

《用python预测高考成绩》
《用python预测高考成绩》

#先按五门总分排序
df_w2 = df_w.sort_values(by='五门总分',ascending=False)
#重命名行名(index):排序后的列索引值是之前的行号,需要修改成从0到N按顺序的索引值
df_w=df_w2.reset_index(drop=True)
df_w.head()

《用python预测高考成绩》
《用python预测高考成绩》

从上表中我们可以看到

1、最高分(max)和最低分(min)相差非常大,说明学生成绩个体差异很大。

2、平均值(mean)低于中们数(50%),说明成绩差的学生拖后腿严重。

下面我们用更直观的图表来分析

# 再进行数据可视化

fig = plt.figure(figsize=(18,10))
ax1 = plt.subplot2grid((1,1),(0,0))

zf_mean = df_w['五门总分'].mean() # 五门总分平均数
pm_mean = df_w['总分排名'].mean() # 总分排名平均数 
w_num = len(df_w)                 # 文科生学生数量
sanmen = df_w['语文']+df_w['数学']+df_w['英语']
x = range(w_num)

ax1.scatter(x, df_w['语文'], color='r', edgecolor='none', s=10)
ax1.scatter(x, df_w['数学'], color='g', edgecolor='none', s=10)
ax1.scatter(x, df_w['英语'], color='b', edgecolor='none', s=10)

ax1.plot(df_w['五门总分'],label='五门总分',color='b',lw=0.8)
ax1.plot(sanmen,label='三门总分', color='r',lw=0.8)
# 填充颜色
ax1.fill_between(x,df_w['五门总分'],sanmen, facecolor='g', alpha=0.4)

# 五门总分平均分点
ax1.scatter(pm_mean,zf_mean, color='r', s=100)

# 画水平线
ax1.axhline(100, color='k', lw=0.8)
# 画垂直线
ax1.axvline(pm_mean, color='k', lw=0.6, linestyle = "dashed")

#调整坐标轴, w_num为学生人数,500为五门总分最高分
plt.axis([0,w_num, 0, 500])
plt.xlabel('学生排名',fontsize=18)
plt.ylabel('分数',fontsize=18)
plt.title('上海某区高考二模成绩排名表\n(文科生)',fontsize=25)
plt.legend()
plt.show()

《用python预测高考成绩》
《用python预测高考成绩》

上图说明:

1、纵坐标表示成绩,横坐标表示排名

2、红点表示语文,结点表示数学,蓝点表示英语,他们的高低分布表示分数的高低。

3、绿色填充部分表示“ 加一学科 + 综合”和的成绩。(五门总成绩-三门语数英成绩和)

4、垂直虚线表示排名平均数位置,大红点表示总分平均分。

5、沿着横坐标往右,每一个垂直线表示一个学生的成绩。(为使图像简洁,网络线没画)

如果只分析语文、数学、英语对总成绩的影响,我们可以得出以下结论:

1、成绩好的学生这三门成绩相对都很好,成绩好的学生英语成绩普遍较好

2、极个别同学偏科非常严重,英语最容易得高分,数学失分最严重。

3、三科中语文成绩差值最小,也就是上面分析到描述统计信息中的标准差(std)值最小。所以对总分影响最小

理科生分析略。

四、分析全部学生

下面开始对全部学生的分析。

PS:以下分析参考自ButtersPC,感谢

首先,我们对“学科”列进行分组(groupby),来看一个各科目的学生情况:

# 按学科分组,再对统计准考证数查看各科目的考和人数
g_xueke = df_new.groupby('学科')
g_xueke['准考证号'].count().sort_values(ascending=False)
学科
化学    1072
物理     758
历史     383
生物     261
政治     212
地理     136
Name: 准考证号, dtype: int64

紧拉着,我们对各学科考生的平均成绩状况进行一个大致的判断:

# 各学科考生的平均分
g_xueke[['语文']].mean().sort_values(by='语文', ascending=True)
g_xueke[['数学']].mean().sort_values(by='数学', ascending=True)
g_xueke[['英语']].mean().sort_values(by='英语', ascending=True)
g_xueke[['三门总分']].mean().sort_values(by='三门总分', ascending=True)
g_xueke[['五门总分']].mean().sort_values(by='五门总分', ascending=True)

得到表格如下

《用python预测高考成绩》
《用python预测高考成绩》

我们可以得出以下结论:

1、选化学的学生最多,其次是物理,最少的是生物。

2、政治班语文平均分最高,物理班其次。

3、物理班英语平均分最高,化学班其次。

4、物理班三门总分平均分和五门总分平均分最高,其次是化学。

总体来说物理班的总体实力最强,五门总分平均分高的学生,语文、数学、英语成绩也普遍较好,和之前分析文科班的情况相似。

再业,我们对“学校”特征进行分组(groupby):

# 按照学校分组,并查看各学校学生数量
g_xuexiao = df_new.groupby('学校')
g_xuexiao['准考证号'].count().sort_values(ascending=False)

学校
行知中学       520
上大附中       447
吴淞中学       352
罗店中学       310
宝山中学       287
顾村中学       168
通河中学       167
行知实验       136
高境一中       104
和衷高中       100
淞浦中学        99
上大附中新疆部     66
同洲模范        26
行中中学        22
建峰高中        18
Name: 准考证号, dtype: int64

这边我们发现了3组异常值:

同洲模范、行中中学、建峰高中三所学校的人数比较奇怪,只有20人左右

查阅网上资料后了解到:

1、行中中学是行知中学放置借读生名额的学校(为了不影响升学率的手段)

2、建峰高中是一所高职,其中会参加高考的学生并不多,因此参加高考模拟考的学生也不多

3、许多人指责同洲模范高中部很差(似乎初中部还不错?),可能校方有意收缩高中部招生

同样地,我们对各学校考生的平均成绩状况进行一个大致的判断:

# 各学校考生的平均分
g_xuexiao[['语文']].mean().sort_values(by='语文', ascending=True)
g_xuexiao[['数学']].mean().sort_values(by='数学', ascending=True)
g_xuexiao[['英语']].mean().sort_values(by='英语', ascending=True)
g_xuexiao[['三门总分']].mean().sort_values(by='三门总分', ascending=True)
g_xuexiao[['五门总分']].mean().sort_values(by='五门总分', ascending=True)

得到表格如下

《用python预测高考成绩》
《用python预测高考成绩》

得到的结果是:

语文平均分第一:罗店中学

数学平均分第一:行知中学

英语平均分第一:吴淞中学

三门平均分第一:行知中学

五门平均分第一:行知中学

有趣的是,行知中学数据平均分第一,并且也获得了三门平均分第一和五门平均分第一

难道数学考得好,更容易拿更高的名次?

从上面的文科生分析我们可以得出,数学的离散性非常大,标准差(std)也最大。

我们再尝试通过皮尔森相关系数验证一下(皮尔森相关系数能够体现两组数据之间的线性关系):

# 分析各科成绩与总分之间的相关系数
df_new[['数学','语文','英语','三门总分','五门总分']].corr()

《用python预测高考成绩》
《用python预测高考成绩》

果然数学与总分的相关系数最高,英语略低于数学,语文最低,而且低很多

我们进一步观测语数英成绩这三组的数据:

# 获取描述统计信息
df_new[['数学','语文','英语']].describe()

《用python预测高考成绩》

我们发现数学的标准差最大,这说明了数学成绩离散程度比较高,每一分的考生人数比较少,因此:数学每提高1分能干掉的其他考生比其他科目少,所以似乎看来提高数学成绩是收益最低的?

的确,数学没提高1分,对于考生在数学考试上的排名提升效果较小,但是在实践考试中我们是按照语数英三门科目加总后进行排名的(而且在加总的时候不分配权重),这就说明数学的1分,英语的1分,语文的1分,在最终三门总排名上的影响是等价的。

我们再回到数学标准差较大的讨论上,我认为数学成绩方差高是一种现象,导致这种现象的是因为数学的评分机制的关系:数学题不会就是不会,经常会出现一道大题20份只拿1分的情况(解: +1分),而语文不会做也能瞎诌诌,英语则题量比较大,得分点分配的很散。再进一步说,就是方差高说明考生在该项考试中成绩差距显著,考生们更容易在该项考试中被拉出等第,也更容易方便学校来选拔考生(之前复旦大学自主招生千分考项目,应该也是同样的思路,高方差为了更便于筛选考生)。

举个例子就是说:假设某个考生A,数学略高于平均水平,英语语文略低于平均水平,在数学考试高方差的放大下,最后考生A的三门总分排名可能是高于平均水平的。而考生B,语文略高于平均水平,数学英语略低于平局水平,在语文考试低方差的影响下,最后考生B的三门总分排名往往是低于平均水平的。

五、结论

最终我得出的结论是,如果将考试分为n门,理论上来说这n门的最终成绩的方差应该是近似的,如果其中有一门的方差偏高,说明这一门更能凸显考生之间的差距(也就是可以拉开排名上的差距),如果作为考生,应该在方差大的科目上多努力,这样有助于最后提高排名(当然是在最终成绩不加权的情况下)。

(以上分析结论复制自ButtersPC)向你学习!

    原文作者:youhoho
    原文地址: https://zhuanlan.zhihu.com/p/35856762
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞