matlab数据归一化_数据分析2020年全国各省高考成绩分布情况

本文通过MATLAB对2020年全国部分省市高考成绩进行数据归一化处理,分析各省市分数分布、平均值与中位数。利用Python读取和整理数据,探讨不同省份的高考政策与统计方式,以及数据处理思路。重点展示了归一化后的成绩分布图,并对比了北京、河南等高考大省与小省之间的差异。
摘要由CSDN通过智能技术生成

1e492b32-702e-eb11-8da9-e4434bdf6706.png

开始

突发奇想, 想看下高考成绩的分布, 如果把每个省市的成绩划线成0-100 分会怎么样,简单的来说, 认为最高分的考了100分,最低分考了0分, 计算一下各个分数段的人数就好了,

顺便可以用这个数据看每个省市的一本线划分比率,还有其他相关的数据,

看起来还是比较简单的, 动手试试

数据收集

网上找了一下, 每年的高考人数, 现在已经超过千万人高考了,河南更是超过了100万, 数据来源:新浪教育 https://edu.sina.cn/zt_d/gkbm

20492b32-702e-eb11-8da9-e4434bdf6706.png

这个表的数据是统计的全国各个省市(除港澳台)之外的数据, 各个省市在出成绩之后会出各自的一分一段表, 统计每一分的成绩的人数, 我们以这个数据为准, 由于个人还是没有太多精力去收集数据的,网上找到了 高考100-一分一段表 这个网站, 给出了各个省市的一分一段表, excel 版本, 稍微检查了一下, 数据应该是对的,我就暂时以这个数据为准,

数据太多, 我暂时只做 35万 以上人的省市,只有11个省市,加上 北京上海两个城市的数据, - 河南 - 河北 - 广东 - 广西 - 湖南 - 湖北 - 江西 - 贵州 - 安徽 - 四川 - 山东 - 北京 - 上海

其中北京上海不分科,山东是选择一门考试进行考核, 所以 一共23个数据表,后续的话,我尽量将数据也一并上传了

21492b32-702e-eb11-8da9-e4434bdf6706.png

数据整理

上面也提到了北京上海山东的分科比较特殊, 我们就按文理一起算,每个省都是给出最高分及以上的数据, 然后给出100分及以下的数据,但是不是每个省都是100分以下,所以还要特殊考虑,

不同高考政策与分类

山东的高考政策具体不清楚, 但是似乎是考生是在6门副科中任选3门,从一图了解山东高考改革要点 这里查到的

22492b32-702e-eb11-8da9-e4434bdf6706.png

我们就不做分科了, 直接看山东的全体成绩即可。

不同统计方式

北京的人数更少,在400分以下每10分段给出人数,我们为了便于方便 默认每个分数平均人数, 比如 390-399分段的人有813人,我们认为每个分段都有81.3人,暂时这么处理。

23492b32-702e-eb11-8da9-e4434bdf6706.png

不同省市对于最高分数的表示都是 最高分数及以上, 但是对于最低分数的处理就不太一样了, 这里不做评价 比如很多省市是合并在一起 100分以下总计, 有些则只是100分的成绩, 100分以下的成绩是没有给出的,这里最后处理的时候, 我们把0分的人都删除了, 只计算1-100 的人,反正不影响整个曲线

24492b32-702e-eb11-8da9-e4434bdf6706.png

最终我们整理得到数据表, 每个Sheet 表示一个省市的文理科目,然后最上面一行数据分别对应 总分,人数, 累计人数,

25492b32-702e-eb11-8da9-e4434bdf6706.png

数据处理

数据处理思路

这里为了方便 顺手用 Python 来做的, 使用的 pandas 读取的 excel 文件, 我们统计所有的数据的目标就是 将成绩化为 0-100分 那么

对于每个省的成绩将其调整到 [0,100], 这里使用的是 四舍五入, 导致实际在计算过程中的数据会重叠,比如相邻的两个成绩一个舍去,一个入上,在统一分数,导致数据噪声较大, 这是使用 一维的中值滤波平滑一下数据就好了,

以河南文科为例, 我们直接绘制归一化之后的成绩并进行中值滤波之后对比, (图为测试过程中归一化到500分的图像,不影响理解)

26492b32-702e-eb11-8da9-e4434bdf6706.png

各省市分数分布

我们在之前已经整理得到的数据, 然后我们 就要动手做了,

# 整理数据,将各省市的成绩归一到100分之后的分布比率

# 引入 pandas
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import scipy.signal as ss

# 设定中文字体
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
# 设定图像尺寸 与分辨率
plt.rcParams['figure.figsize'] = (8.0, 4.0) # 设置figure_size尺寸
plt.rcParams['image.interpolation'] = 'nearest' # 设置 interpolation style
plt.rcParams['savefig.dpi'] = 300 #图片像素
plt.rcParams['figure.dpi'] = 300 #分辨率

# 将成绩统一到 [0,] 区间
MAX_SCORE = 100
MIN_SCORE = 0

data_file = 'Data/data.xlsx'
res_file = 'Data/res-'+str(MAX_SCORE-MIN_SCORE)+'.xlsx'

# 读取excel , 获取所有表单名字
excel_info = pd.ExcelFile(data_file)

all_data = {}
all_data_ratio = {}
# 获取表中的每一个数据文件 并将数据归一化到 0-500
for index in range(len(excel_info.sheet_names)):
    # 读取每一个表单
    cur_sheetname = excel_info.sheet_names[index]
    df_sheet = pd.read_excel(data_file, sheet_name=cur_sheetname)

    # 获取每一个表中的 总分数 和对应分数的人数
    scores = df_sheet[df_sheet.columns.values[0]]
    nums = df_sheet[df_sheet.columns.values[1]]

    # 数据 对应 每个分数的人数 表
    ROWS = MAX_SCORE - MIN_SCORE + 1
    trans_scores_nums = [0] * ROWS

    rows = len(scores)
    cur_max_score = scores[0]
    cur_min_score = scores[rows - 1]

    cur_index = 0;
    for s in scores:
        # 计算 变换之后的分数 四舍五入
        trans_score = (int)(round((s - cur_min_score) / (cur_max_score - cur_min_score) * (MAX_SCORE - MIN_SCORE)))

        # 在计算分数的位置上 加上对应分数的人数
        trans_scores_nums[trans_score - 1] += nums[cur_index];
        cur_index += 1

    # 数据稍微处理一下, 做简单的平滑处理, 去除最低分数据
    except0data = [0] * (ROWS - 1)
    for i in range(ROWS - 1):
        except0data[i] = trans_scores_nums[i + 1];

    # 中值滤波去除噪点
    smooth_trans = ss.medfilt(except0data, 7)

    # 将数据转换成比例, 更具有一般性
    sum = 0
    smooth_trans_ratio = [0] * (ROWS - 1)
    for i in range(ROWS - 1):
        sum += smooth_trans[i]

    for i in range(ROWS - 1):
        smooth_trans_ratio[i] = smooth_trans[i] / sum

    all_data[cur_sheetname] = smooth_trans
    all_data_ratio[cur_sheetname] = smooth_trans_ratio

    print('正在进行 {0}/{1}, 表名:{2}'.format(index + 1, len(excel_info.sheet_names), cur_sheetname))

    # plt.plot(smooth_trans2)
# write_data = pd.DataFrame(all_data)
# write_data.to_excel(res_file,sheet_name='res')
write_data_ratio = pd.DataFrame(all_data_ratio)
write_data_ratio.to_excel(res_file, sheet_name='ratio')

print('已经完成,存储文件:{0}'.format(res_file))

我们在这个程序里面主要是 将数据提取出来, 计算成 100分制之后,重新存入 excel 表中,其中人数部分换成了各省市的人数比率,也方便查阅后续的数据 ( 因为我感觉 plt 绘制图像不好看,这边使用了MATLAB 进行图像的绘制过程)

% 将 原始数据绘制出来 并计算平均值和中值

% 读取 excel 数据  获取名称以及各列名称
data_file = 'Data/res-100.xlsx';
res_ratio = xlsread(data_file,1,'B2:X501');
res_name = {'河南文科',    '河南理科',      '北京',       '上海',    '河北文科',    '河北理科',    '山东',    '广东文科'    '广东理科'    '湖北文科',    '湖北理科',    '湖南文科',    '湖南理科',    '四川文科',    '四川理科',    '安徽文科',    '安徽理科',    '广西文科',    '广西理科',    '贵州文科',    '贵州理科',    '江西文科',    '江西理科'};

figure()
hold on
[rows,cols] = size(res_ratio);
avg = zeros(cols,1);
media =zeros(cols,1);
for i=1:cols
    % 绘制百分比率图
    plot(res_ratio(:,i)*100);

    % 计算平均值  中值
    media_l = 0.5;
    media_find_flg = 0;
    for j = 1:rows
        avg(i) = avg(i) + j*res_ratio(j,i);

        % 统计比率超过一半的 数之后就是中值 找到后就不更新了
        if(media_find_flg ==0)
              if(media_l >0)
                  media_l = media_l - res_ratio(j,i);
              else
                  media(i) = j;
                  media_find_flg = 1;
            end
        end
    end
end
legend(res_name);

% 创建 xlabel
xlabel({'归一化到100分后成绩'});

% 创建 title
title({'各省市归一化成绩分布比率'});

% 创建 ylabel
ylabel({'单位成绩分布比率'});

最终我们得到了这样的一副图, 细节部分比较多,且数据噪声较大,但是数据的整体趋势大概明白了,噪声较大的黄色的线是北京的,暂时不做过多分析

27492b32-702e-eb11-8da9-e4434bdf6706.png

各省市分数平均值与中值

我们这里的计算平均值就是 每分段人数乘以该分段的比例,最终得到的结果, 然后, 中值这里简单除暴, 找到中间比率所在的区间就好了, 代码没有去过多处理, 能跑出来结果就好

29492b32-702e-eb11-8da9-e4434bdf6706.png

数据简单分析

我们在上一章节给出了一张图, matlab 绘制的图的颜色比较接近, 建议下载原图观看,给出了分布图, 我们把数据最为特殊的几条线单独绘制一下,

  • 最偏右的 黄色 北京
  • 最偏左的 紫色 广西文科
  • 最高的 浅蓝色 贵州文科
  • 最平均的 浅紫色 湖北理科
  • 双峰的 蓝色 江西文科

2a492b32-702e-eb11-8da9-e4434bdf6706.png

其实这些形态是有独特的意义的,理论上的曲线是正太分布的,但是由于各种原因,我们以实际曲线为主, - 靠右表示 数据整体偏大 - 靠左整体偏小 - 最高的表示数据比较集中, - 最低的表示数据分布均匀 - 双峰的表示数据割裂严重(我瞎编的)。。。

就总体而言, 各个省市的成绩的峰值(众数)也主页也分为两个部分,部分省市的峰值在40分左右,主要包括河南文科,河北文科,湖北文科,广西文科,广西理科 剩下的分数的众数都集中在60分多一点的位置,

emmm, 就这么多了, 再多的分析也没有太多用, 毕竟北京NB

剩下的部分就是 高考本科上线率这种数据了, 但是各省对于本科的分数线真是不同

2b492b32-702e-eb11-8da9-e4434bdf6706.png

我给出的数据是我在各地高考历年分数线(批次线) 这个网页上能看到2020 年各省高考批次线, 一般的省市都是划分 1本2本专科, 除了北京,上海,河北,山东,广东 后面想办法再做吧, 估计会不做了

高考大省与高考小省

我们拿高考大省河南河北然后对比上海和北京, 看下数据 其实这里应该去找数据轴上的最明显特征的线, 具体数据自己分析好了

但是我们暂时只看这几个数据,

2d492b32-702e-eb11-8da9-e4434bdf6706.png

2f492b32-702e-eb11-8da9-e4434bdf6706.png

都是前面给出的数据, 我们绘制出来了

30492b32-702e-eb11-8da9-e4434bdf6706.png

北京的成绩是明显优于河北的,河南和上海的数据其实是一直的,即使是在全部曲线图上也算比较中间的类型了,

总结

搞了半天, 屁用没有,就是手痒然后就搞了一大堆, 越搞越多, 后续还有一堆要做的,

根据本篇数据而言, 北京的成绩是比全国各个省市的成绩要好的,可能与培养方式不同吧,

其实这种分数分布并不一定是培养造成的, 还有部分是各省考试情况不同导致的,所以数据仅供参考, 北京NB

备注

我将所有的数据都存在了 Github 上

https://github.com/SChen1024/GaoKao

有兴趣的可随便拿数据进行分析, 后续还会做完最后一点

PS:第一次在知乎发文章 后台真的一言难尽, markdown 功能是废的一样,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值