Advertisement

2018研究生数学建模成绩分析

阅读量:

2018第十五届全国研究生数学建模竞赛完整赛题下载
2018研究生数学建模成绩分析,主要从以下几个方面进行分析
建模成绩数据来源:2018研究生数学建模成绩汇总

依据‘队长所在单位’信息,汇总每个学校获得的奖项数量,并绘制柱状图进行可视化展示

复制代码
    #coding:utf-8
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    from geopy.geocoders.baidu import Baidu
    import os
    import time
    sns.set(style="whitegrid")
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为黑体
    plt.rcParams['axes.unicode_minus'] = False  # 解决中文字体负号显示不正常问题
    
    path='../data/'
    save_dir='../tmp/'
    data=pd.read_excel(path+'2018建模成绩汇总.xlsx')
    data['奖项']=data['奖项'].apply(lambda x:'一等奖'if x=='一等奖(华为)' else x)
复制代码
    # 按'队长所在单位'分别统计获奖数量
    def school_cnt(df):
    school_cnt_df=df[df['奖项']!='成功参与奖'][['奖项','队长所在单位']].groupby(['队长所在单位','奖项']).size().unstack()
    school_cnt_df['获奖数量']=school_cnt_df[['一等奖','二等奖','三等奖']].sum(axis=1)
    school_cnt_df.sort_values(by=['获奖数量','一等奖','二等奖','三等奖'],axis=0,ascending = False,inplace=True)
    school_cnt_df=school_cnt_df[['一等奖','二等奖','三等奖','获奖数量']]
    school_cnt_df=school_cnt_df.reset_index().rename(columns={'队长所在单位':'学校名称'})
    print(school_cnt_df.head(5))
    # school_cnt_df.to_excel(path+'school_cnt.xlsx',encoding='gbk')
    # 用柱状图给出获奖数量最多的前20个学校
    plt.figure(figsize=(15, 10)).subplotpars.update(bottom=0.25)
    sns.barplot(x="学校名称", y="获奖数量", data=school_cnt_df.loc[0:20],
                palette="muted")
    plt.xticks(ha='right', rotation=40)
    plt.savefig(path+'school_cnt.png')
    plt.show()

用柱状图给出获奖数量最多的前20个学校

在这里插入图片描述

2. 按每个学校获奖人数进行统计,并画出柱状图进行展示

复制代码
    # 统计每个学校的获奖人数
    # 思路1:使用双层字典嵌套逐个统计
    # 思路2:groupby
    def team_member_cnt(df):
    team_leader_cnt_df=df[['奖项','队长所在单位']].groupby(['队长所在单位','奖项']).size().unstack()
    team_member_df=team_leader_cnt_df[['一等奖','二等奖','三等奖']]
    team_member_cnt_df1=df[['奖项','第一队友所在单位']].groupby(['第一队友所在单位','奖项']).size().unstack()
    team_member_df=team_member_df.join(team_member_cnt_df1[['一等奖','二等奖','三等奖']],how='outer',rsuffix='_2')
    team_member_cnt_df2=df[['奖项','第二队友所在单位']].groupby(['第二队友所在单位','奖项']).size().unstack()
    team_member_df=team_member_df.join(team_member_cnt_df2[['一等奖','二等奖','三等奖']],how='outer',rsuffix='_3')
    
    team_member_df.rename(columns={'一等奖':'一等奖_1','二等奖':'二等奖_1','三等奖':'三等奖_1'},inplace=True)
    team_member_df['获奖总人数']=team_member_df.sum(axis=1)
    sort_cols=['获奖总人数','一等奖_1','一等奖_2','一等奖_3','二等奖_1','二等奖_2','二等奖_3','三等奖_1','三等奖_2','三等奖_3']
    team_member_df.sort_values(by=sort_cols,ascending=False,inplace=True)
    
    team_member_df=team_member_df.reset_index().rename(columns={'index':'学校名称'})
    print(team_member_df.head())
    team_member_df.to_excel(path+'各学校获奖人数统计.xlsx',encoding='gbk',index=False)
    # 用柱状图给出获奖人数最多的前20个学校
    plt.figure(figsize=(15, 10)).subplotpars.update(bottom=0.25)
    sns.barplot(x="学校名称", y="获奖总人数", data=team_member_df.loc[0:20],
                palette="muted")
    plt.xticks(ha='right', rotation=40)
    plt.savefig(path+'school_cnt_amount.png')
    plt.show()
    
    temp_df=data[data['奖项']!='成功参与奖'][['奖项','队长所在单位','第一队友所在单位','第二队友所在单位']]
    
    
    if __name__=="__main__":
    school_cnt(data)
    team_member_cnt(temp_df)

统计每个学校的获奖人数用柱状图展示

在这里插入图片描述

统计各个学校各个名次及次序的获奖人数信息如下:

在这里插入图片描述

3. 分析A、B、C、D、E、F每个题的获奖数量及占比

复制代码
    # 分析A、B、C、D、E、F每个题的获奖数量及占比
    def get_question_prize_ration(df):
    question_df=df[['队伍编号','题号']].groupby(['题号']).count()
    question_df=question_df.reset_index().rename(columns={'index':'题号','队伍编号':'获奖数量'})
    # prize_sum=question_df['获奖数量'].sum()
    question_df['获奖比例']=question_df['获奖数量']/(question_df['获奖数量'].sum())
    print(question_df)
    question_df.to_excel(save_dir+'每题获奖数量比例.xlsx',index=False,encoding='gbk')
    plt.figure(figsize=(12,6))
    N,width=6,0.35
    ind=np.arange(N)
    plt.subplot(121)
    plt.title('A、B、C、D、E、F每个题的获奖数量')
    plt.bar(ind,question_df['获奖数量'],width=width)
    plt.ylabel('获奖数量')
    plt.xticks(ind,('A','B','C','D','E','F'))
    plt.subplot(122)
    plt.title('A、B、C、D、E、F题获奖比例')
    plt.pie(question_df['获奖比例'],labels=('A','B','C','D','E','F'),startangle=0,radius=0.8,labeldistance=0.5)
    plt.savefig(save_dir+'每个题的获奖数量和比例.png')
    plt.show()
在这里插入图片描述

4. 统计A-F各题的获奖率,并通过饼图的形式进行可视化展示
类比第3问的做法(作者太懒,见谅)

5. 按地图省份绘制每个省的参与人数热力图
类比第6问(作者太懒,见谅)

6. 按地图省份绘制每个省份的获奖人数热力图

复制代码
    # 按地图省份绘制每个省份的获奖人数热力图
    # 调用百度地图API获取每个学校的经纬度信息
    def get_school_info():
    df = pd.read_excel(save_dir+'各学校获奖人数统计.xlsx',encoding='gbk')
    lng_set = []
    lat_set=[]
    for school in df['学校名称']:
        print(school)
        try:
            location = geolocator.geocode(school, timeout=300)
            lng_lat=location.raw['location']
            lng,lat=lng_lat['lng'],lng_lat['lat']
            print(lng,lat)
            lng_set.append(lng)
            lat_set.append(lat)
        except Exception as e:
            print(e)
            time.sleep(5)
            lng_set.append(np.nan)
            lat_set.append(np.nan)
    
    df['lng']=lng_set
    df['lat']=lat_set
    df=df[['学校名称','获奖总人数','lng','lat']]
    df.to_excel(save_dir+'school_loc_prize_nums.xlsx',encoding='gbk', index=False,float_format='%.6f')
    print(df.head())
复制代码
    # 绘制热力地图
    def draw_heatmap(input_path,out_path):
    df=pd.read_excel(input_path,encoding='gbk')
    df=df[df['lng']>0]
    rows=df.shape[0]
    fout=open(out_path,'w',encoding="utf-8")
    fout.write(
    '''<!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <title>2018研究生建模成绩地理位置分析</title>
    <link rel="stylesheet" href="http://cache.amap.com/lbs/static/main1119.css"/>
    <script src="http://webapi.amap.com/maps?v=1.3&key=your-personal-key"></script>
    <script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script>
    <script type="text/javascript" src="http://a.amap.com/jsapi_demos/static/resource/heatmapData.js"></script>
    </head>
    <body>
    <div id="container">
    </div>
    <div class="button-group">
        <input type="button" class="button" value="显示热力图" onclick="heatmap.show()"/>
        <input type="button" class="button" value="关闭热力图" onclick="heatmap.hide()"/>
    </div>
    <script>
        var map = new AMap.Map("container", {
            resizeEnable:false,
            center: [121.5197936,31.2874348],
            zoom: 7
        });
        if (!isSupportCanvas()) {
            alert('热力图仅对支持canvas的浏览器适用,您所使用的浏览器不能使用热力图功能,请换个浏览器试试~')
        }'''
    )
    fout.write("\n\t\t var points = [\n")
    for i in range(0,rows-1):
        fout.write("\t\t\t{'lat':%f,'lng':%f,'count':%d},\n"%(df.iat[i,3],df.iat[i,2],df.iat[i,1]))
    fout.write("\t\t\t{'lat':%f,'lng':%f,'count':%d}];"%(df.iat[-1,3],df.iat[-1,2],df.iat[-1,1]))
    fout.write(
    '''
        //详细的参数,可以查看heatmap.js的文档 http://www.patrick-wied.at/static/heatmapjs/docs.html
        //参数说明如下:
        /* visible 热力图是否显示,默认为true
         * opacity 热力图的透明度,分别对应heatmap.js的minOpacity和maxOpacity
         * radius 势力图的每个点的半径大小   
         * gradient  {JSON} 热力图的渐变区间 . gradient如下所示
         *	{
         .2:'rgb(0, 255, 255)',
         .5:'rgb(0, 110, 255)',
         .8:'rgb(100, 0, 255)'
         }
         其中 key 表示插值的位置, 0-1 
         value 为颜色值 
         */
        var heatmap;
        map.plugin(["AMap.Heatmap"], function() {
            //初始化heatmap对象
            heatmap = new AMap.Heatmap(map, {
                radius: 15, //给定半径
                opacity: [0, 0.8]
                /*,gradient:{
                 0.5: 'blue',
                 0.65: 'rgb(117,211,248)',
                 0.7: 'rgb(0, 255, 0)',
                 0.9: '#ffea00',
                 1.0: 'red'
                 }*/
            });
            //设置数据集
            heatmap.setDataSet({
                data: points,
                max: 5
            });
        });
        //判断浏览区是否支持canvas
        function isSupportCanvas() {
            var elem = document.createElement('canvas');
            return !!(elem.getContext && elem.getContext('2d'));
        }
    </script>
    </body>
    </html>
    '''
    )
    fout.close()
在这里插入图片描述
在这里插入图片描述

通过热力图的数据可以看出:
上海地区是参加研究生数学建模的主要力量;同时也是表现最为突出的地方。
主要原因之一在于上海高校众多。
在上海地区的参赛者中,在'落沪'评分中获得一定的加分优势。
一等奖可加10分;二等奖可加8分;三等奖可加6分。

在这里插入图片描述

这里是整个分析代码的主函数(尾部)

复制代码
    if __name__=="__main__":
    school_cnt(data)
    
    temp_df=data[data['奖项']!='成功参与奖'][['奖项','队长所在单位','第一队友所在单位','第二队友所在单位']]
    team_member_cnt(temp_df)
    
    prize_df=data[data['奖项']!='成功参与奖']
    get_question_prize_ration(prize_df)
    
    # 此处需要替换成你自己的百度地图api_key,去百度地图上申请吧
    api_key = 'your-personal-key' 
    geolocator = Baidu(api_key=api_key)
    get_school_info()
    input_path=save_dir+'school_loc_prize_nums.xlsx'
    out_path=save_dir+'heat_map.html'
    draw_heatmap(input_path,out_path)

7. 总结分析
放上一些中间过程的统计表格:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分析:
(1) 随着上海落沪指标不断优化和发展趋势明显。
上海地区的高校在研究生数学建模中的参赛热情持续高涨,
并远超全国其他地区水平,
在竞争中占据绝对优势位置。
一般而言,
完成建模比赛后达到最低准入标准72分即可满足落沪要求(一等奖增10分、二等奖增8分、三等奖增6分),且与队伍内部成员的具体分工无关。
(2) 在所有参赛学校中,“985/211”高校数量最多的是同济大学。
(3) 2018年的赛题分布情况显示:
C题涉及恐怖袭击事件的数据量化分析和预测研究。
这是一门相对简单易懂的应用学科,
在数据分析能力培养方面具有良好的基础作用,
并且每年的参赛人数均保持在总获奖人数的45%以上。
随着时间推移,“C题”的研究方向逐渐向以大数据技术为核心的领域延伸。
(4) 获得奖项后的喜悦来自于连续四个昼夜的努力付出所换取的结果。
无论最终成绩如何,
在整个过程中的经历都让人感到充实和满足。

记录于 2018 年 11 月 14 日,请将改写内容放置于【

全部评论 (0)

还没有任何评论哟~