暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

用python制作历届冬奥奖牌动态排行榜

运维路书 2022-04-14
33
最近学习用python做可视化数据分析,刚好做了一个冬奥的排行榜。使matplotlib显示动态柱状图,效果如下(最后附实现代码


实现代码如下:



    from turtle import color
    import requests
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import numpy as np
    import os
    '''
    url = 'https://app.sports.qq.com/m/oly/historyMedal'
    res = requests.get(url)
    res_json = res.json()
    his_list = res_json['data']['list']
    df = pd.DataFrame(his_list)
    df.to_json('d:\pycode\pydv\oly_his.json',orient='split',index=False)
    df = df.explode('list')
    df['noc'] = df['list'].apply(lambda x:x['noc'])
    df['gold'] = df['list'].apply(lambda x:x['gold'])
    df['total'] = df['list'].apply(lambda x:x['total'])
    his_data = df[['no','year','country','noc','gold','total']]
    '''


    df = pd.read_json('oly_his.json',orient='split')
    df = df.explode('list')
    df['rank'] = df['list'].apply(lambda x:x['rank'])
    df['noc'] = df['list'].apply(lambda x:x['noc'])
    df['gold'] = df['list'].apply(lambda x:int(x['gold']))
    df['total'] = df['list'].apply(lambda x:int(x['total']))
    his_data = df[['rank','no','year','country','noc','gold','total']]
    his_data = his_data.replace('俄罗斯奥委会','俄罗斯')
    #设置字体,显示中文
    plt.rcParams["font.family"]=["Simhei"]
    #设置动态图上限
    plt.rcParams['animation.embed_limit'] = 2**128
    #设置颜色
    #co = ICC.ColorOrder(['Red','Purple','Yellow','Orange','green',
    # 'blue'],'cross')


    def region_set(x):
    if (x in ["韩国", "日本", "中国", "朝鲜"]):
    return "Asia"
    elif (x in ["美国","加拿大"]):
    return "The Americas"
    elif (x in ["澳大利亚","新西兰"]):
    return "Oceania"
    else:
    return "Europe"
    '''
    def color_set(x):
    if (x =="Asia"):
    return "#FF4500"
    elif (x =="The Americas"):
    return "#FFA500"
    elif (x =="Oceania"):
    return "#0080FF"
    elif (x =="Europe"):
    return "#9ACD32"
    his_data['color'] = his_data['region'].apply(lambda x:color_set(x))
    '''
    his_data['region'] = his_data['noc'].apply(lambda x:region_set(x))
    #颜色字典
    colors_region = dict(zip(
    ['Asia', 'Oceania', 'Europe', 'The Americas'],
    ['#FF4500','#0080FF','#9ACD32','#FFA500']
    ))
    fig, ax = plt.subplots(figsize =(4,6),dpi=150)


    def gold_rank():
    grouped =his_data.groupby(['noc'])['gold']
    gold_sum = grouped.sum().reset_index()
    gold_sum = gold_sum.sort_values(['gold'])
    ax.barh(gold_sum['noc'],gold_sum['gold'])
    #plt.savefig(r'Winter_Oly_Gold_Sum.png',width=5,
    # height=7,dpi=900,bbox_inches='tight')
    plt.show()


    def total_rank():
    total_sum =his_data.groupby(['noc'])['total'].sum().reset_index().sort_values(['total'])
    ax.barh(y=np.arange(len(total_sum['noc'])),width=total_sum['total'],tick_label=total_sum['noc'])
    plt.show()


    def total_rank_per_term(cur_year):
    #cur_year = "2006"
    if his_data[his_data['year'].eq(cur_year)].empty is False:
    cur_data = (his_data[his_data['year'].eq(cur_year)]
    .sort_values(['total']))
    #清除当前的axes对象,重新绘制
    #重要,如果不清除前一个对象,会造成图像重叠
    plt.cla()
    #绘制水平柱形图
    ax.barh(y=cur_data['noc'],width=cur_data['total'],
    color = [colors_region[x] for x in cur_data['region']])
    #添加标签
    for i, (name,value,region) in enumerate(zip(cur_data['noc'],cur_data['total'],cur_data['region'])):
    ax.text(value,i, name, ha="right",size=6)# 如:中国:国家名
    ax.text(value + 0.1, i,value,
    color = colors_region[region],ha = 'left', va = 'center',
    fontweight = 'bold',size = 10)
    #添加年份标签
    ax.text(1, 0.4, cur_year, transform = ax.transAxes, size =60, ha = 'right',
    color="gray",alpha=.5,fontfamily = "Simhei" )

    #刻度标签形式
    #设置X轴刻度边界
    ax.set_xlim([0,cur_data['total'].max()+5])
    #设置X轴刻度在顶部
    ax.xaxis.set_ticks_position('top')
    #设置X轴刻度参数
    ax.tick_params(axis='x',colors = 'gray',labelsize = 10,top=False,bottom = False)
    ax.margins(0,0.01)
    #设置显示哪个轴的网格线
    ax.grid(which='major',axis='x',ls='-')
    #坐标轴是否在最下面图层
    ax.set_axisbelow(True)
    #隐藏Y轴标签
    #ax.set_yticklabels([])
    #隐藏Y轴标签和刻度
    ax.yaxis.set_visible(False)

    ax.text(1,-0.03,'by.DengYue',transform = ax.transAxes,color ='gray',ha = 'right',fontsize=12)
    ax.text(0,1.1,'历届冬奥会奖牌榜',transform = ax.transAxes,
    color ='gray',ha = 'left',fontsize =10)
    #添加图列
    labels = list(colors_region.keys())
    handles = [plt.Rectangle((0,0),1,1,color=colors_region[label]) for label in labels]
    bar_legent=plt.legend(handles,labels,loc="lower right",title="区域",fontsize=8)
    bar_legent.get_title().set_fontsize(fontsize=8)
    plt.box(False)




    def gold_rank_per_term(cur_year):
    #cur_year = "2006"
    if his_data[his_data['year'].eq(cur_year)].empty is False:
    cur_data = (his_data[his_data['year'].eq(cur_year)]
    .sort_values(['gold']))
    #清除当前的axes对象,重新绘制
    #重要,如果不清除前一个对象,会造成图像重叠
    plt.cla()
    #绘制水平柱形图
    ax.barh(y=cur_data['noc'],width=cur_data['gold'],
    color = [colors_region[x] for x in cur_data['region']])
    #添加标签
    for i, (name,value,region) in enumerate(zip(cur_data['noc'],cur_data['gold'],cur_data['region'])):
    ax.text(value,i, name, ha="right",size=8)# 如:中国:国家名
    ax.text(value + 0.1, i,value,
    color = colors_region[region],ha = 'left', va = 'center',
    fontweight = 'bold',size = 10)
    #添加年份标签
    ax.text(1, 0.4, cur_year, transform = ax.transAxes, size =60, ha = 'right',
    color="gray",alpha=.5,fontfamily = "Simhei" )

    #刻度标签形式
    #设置X轴刻度边界
    ax.set_xlim([0,cur_data['gold'].max()+5])
    #设置X轴刻度在顶部
    ax.xaxis.set_ticks_position('top')
    #设置X轴刻度参数
    ax.tick_params(axis='x',colors = 'gray',labelsize = 10,top=False,bottom = False)
    ax.margins(0,0.01)
    #设置显示哪个轴的网格线
    ax.grid(which='major',axis='x',ls='-')
    #坐标轴是否在最下面图层
    ax.set_axisbelow(True)
    #隐藏Y轴标签
    #ax.set_yticklabels([])
    #隐藏Y轴标签和刻度
    ax.yaxis.set_visible(False)

    ax.text(1,-0.03,'by.DengYue',transform = ax.transAxes,color ='gray',ha = 'right',fontsize=12)
    ax.text(0,1.1,'历届冬奥会金牌榜',transform = ax.transAxes,
    color ='gray',ha = 'left',fontsize =10)
    #添加图列
    labels = list(colors_region.keys())
    handles = [plt.Rectangle((0,0),1,1,color=colors_region[label]) for label in labels]
    bar_legent=plt.legend(handles,labels,loc="lower right",title="区域",fontsize=8)
    bar_legent.get_title().set_fontsize(fontsize=8)
    plt.box(False)





    #total_rank_per_term(2018)
    total_animator = animation.FuncAnimation(fig,total_rank_per_term, frames=[1924,1928,1932,1936,
    1948,1952,1956,1960,1964,1968,1972,1976,1980,
    1984,1988,1992,1994,1998,2002,2006,2010,2014,2018,2022],
    interval=500)
    ''' gold_animator = animation.FuncAnimation(fig,gold_rank_per_term, frames=[1924,1928,1932,1936,
    1948,1952,1956,1960,1964,1968,1972,1976,1980,
    1984,1988,1992,1994,1998,2002,2006,2010,2014,2018,2022],
    interval=500) '''
    #HTML(barh_animator.to_jshtml())
    plt.show()
    #配置ffmpeg程序路径
    ffmpegpath = os.path.abspath("D:\\ffmpeg\\bin\\ffmpeg.exe")
    plt.rcParams["animation.ffmpeg_path"] = ffmpegpath
    writer = animation.FFMpegWriter()
    #total_animator.save("olympic_total.mp4",writer=writer)
    #gold_animator.save("olympic_gold.mp4",writer=writer)


    文章转载自运维路书,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论