用Matplotlib实现世界GDP动态排名

本篇博客中的代码可以在jupyter notebook中运行。

2023/01大修博客。

因为在学习Tableau的时候遇到了一个GDP动态排名图的问题,写这篇博客主要是想用Python来实现该动态图,最终实现效果如下图1。

图1 GDP动态排名图

1. 数据准备

1.1 读入原始数据

本篇博客用到的GDP数据下载地址如下:

链接:https://pan.baidu.com/s/1Joa4i4mM2vHgRVS9p8I2SQ 
提取码:e3tc

先读入数据,并将无用字段删除,具体代码如下:

import pandas as pd
data=pd.read_csv(r'C:\Users\sunta\Downloads\main_country.csv')
gdp_rank_data=data.drop(['Country_Code','Indicator_Name','Indicator_Code'],
                        axis=1)

经过处理之后的部分数据截图如图2:

图2

1.2 计算GDP排名

接下来需要计算出各国在不同年份的GDP排名,从图1上可以发现以下几点:

  • 每一年GDP最高的国家排在最上边;
  • 这张GDP动态图只展示排名前10的国家及其GDP数据;

基于以上两点,我们要计算的GDP排名数据需要满足以下条件:逆序排序;GDP最大值对应的排名值设为10。这样的排名可以保证GDP最大的10个国家的排名值为10到1,方便排除未进入前10的国家。GDP排名计算代码如下:

for year in gdp_rank_data.columns[1:]:
    #rank()逆序时GDP最大值的计算结果为1,为了将其映射到10上,用11减去rank()的计算值
    gdp_rank_data[year+'_rank']=11-gdp_rank_data[[year]].rank(ascending=False)
    #更改GDP的单位,除以10亿(1e10为其科学表示法)
    gdp_rank_data[year]=gdp_rank_data[year]/1e10

经过处理之后的1960年的GDP及其排名数据如下图3:

图3

2. 具体画图

在具体写代码画图之前,关于图1有以下几点需要说明:

  • 图1中的动态图能够看到GDP变化的动态过程,为了实现这种动态的效果,这里将一个年份到下一年份的变化分5步来完成。以1960年到1961年GDP变化为例,中国的GDP从59亿下降为50亿。将这9亿的分5步来完成,第i步下降到[59-(9/5)*i]亿元,其对应的排名数值也这样分5步来变化。所以图1这张动态图其实是由286((2017-1960)*5+1)张常规的水平条形图组成的。这也是for循环中286这个数字的来源。
  • 图1中代表每个国家的柱子的四个角各自加了一个圆点,这是为了美观而做,也可以不加;
  • 图1中X轴需要随着每个GDP数据的增长而延长,这里是通过扩大比例尺而实现的。
  • 为了在视觉上固定右下角的年份标签,将年份标签的水平位置固定到0.8*X轴最大值的位置上。

具体代码如下:

import matplotlib.pyplot as plt
import matplotlib
import matplotlib.animation as animation
import imageio
%matplotlib auto

matplotlib.rc('font', family='SimHei', weight='bold')
plt.rcParams['axes.unicode_minus'] = False

fig,ax=plt.subplots()
#去掉右侧和上边的边框线
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['left'].set_color('none')

colors=['cornflowerblue','tomato','coral','darksalmon','orangered','sienna','chocolate',
        'saddlebrown','orange','burlywood','olive','olivedrab','greenyellow','lawngreen',
        'orchid','palegreen','aqua','deepskyblue','dodgerblue','darkviolet','crimson']

image_list=[]
for i in range(286):
    ax.cla()
    ax.set_ylim(0,11)
    y_ind=str(1960+i//5)
    if i==285:
        data=gdp_rank_data[['Country_Name',y_ind,y_ind+'_rank']]
        data['step_rank']=data[y_ind+'_rank']
        x_gdp=data[y_ind]
    else:
        next_y_ind=str(1960+i//5+1)
        data=gdp_rank_data[['Country_Name',y_ind,y_ind+'_rank',next_y_ind,
                           next_y_ind+'_rank']]
        data['step_rank']=data[y_ind+'_rank']+(data[next_y_ind+'_rank']
                                           -data[y_ind+"_rank"])/5*(i%5)
        x_gdp=data[y_ind]+(data[next_y_ind]-data[y_ind])/5*(i%5)
    y_labels=data.index
    bars=ax.barh(data['step_rank'],x_gdp,color=[colors[i] for i in data.index],height=0.5)
    data=data.sort_values('step_rank',na_position='first')
    ax.set_yticks(data[data['step_rank']>=0]['step_rank'].values[-10:])
    ax.set_yticklabels(data[data['step_rank']>=0]['Country_Name'].values[-10:])
    ax.set_title("世界GDP动态排名(1960年-2017年)(单位:十亿)")
    for bar in bars:
        if bar.get_y()>0:
            width=bar.get_width()
            plt.text(width+ax.get_xlim()[1]*0.02,bar.get_y()+0.125,"{:.2f}".format(width))
            #在柱子的四个角上加上四个点
            plt.plot([0,width,width,0],
                     [bar.get_y(),bar.get_y(),bar.get_y()+0.5,bar.get_y()+0.5],color=bar.get_facecolor(),
                    marker='o')
    plt.text(int(ax.get_xlim()[1]*0.8),2,y_ind+'年',fontsize=18)
    if i%5==0:
        plt.pause(3)
    else:
        plt.pause(0.3)
    plt.savefig('tmp.png')
    image_list.append(imageio.imread('tmp.png'))
imageio.mimsave('test.gif',image_list,duration=1)

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值