数据及代码链接:https://pan.baidu.com/s/1Xc79pa0uCTLV3vV1VcdnuA
提取码:vf1b
代码的注释很全。
抖音上经常刷到随时间变化的某一指标的的排序条形图视频,我参考相关文章,学习了一下如何绘制这种动态排序图。绘制出来的效果如下图所示。数据不是很多但是用于学习制作动态图是可以的了。
该图的数据为1990-2018年前十2010年不变美金GDP的国家排序,数据来源是世界银行。
绘制该图的编程语言为python,主要应用的包为matplotlib,在绘图前需先导入所需要的包。
#导入需要的包
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.animation as animation
from IPython.display import HTML
数据预处理
- 读取文件
此处用pandas读取csv文件,将文件中的“..”设为缺失值并更改列名。
#设置读取数据后的列名
new_name=['Series Name','Series Code','Country Name','Country Code','1990',
'2000','2010','2011','2012','2013','2014','2015','2016','2017','2018','2019']
df = pd.read_csv("GDP.csv",names = new_name, header=0,na_values='..')#读取文件,将数据中的“..”设为缺失值
df.head(5)
- 转换数据类型
df.drop(['Series Name', 'Series Code','2019'], axis=1, inplace=True) #2019的数据还未统计,予以删除,删除指标名称列和指标编码列
df[['1990','2000','2010','2011','2012','2013','2014','2015','2016','2017','2018']].astype('float64',errors='ignore')
作图前准备
为了图片美观以及区分国家,我们给每个出现在前十的国家一个颜色,此时我们需要统计出这些出现的国家。
依次选出各年前十的国家求并集。
#将1990至2018年排在前十的国家都找出来,集合去重转为列表
years=['1990','2000','2010','2011','2012','2013','2014','2015','2016','2017','2018']
country=set()
for i in range(len(years)):
year=years[i]
dff = (df[['Country Name','Country Code',year]].sort_values(by=year, ascending=False).head(10))
coun=dff['Country Name'].tolist()
coun=set(coun)
country=country|coun #求并集
country=list(country)
country.sort()
得到的国家名单为['Brazil', 'Canada', 'China', 'France', 'Germany', 'India', 'Italy', 'Japan', 'Russian Federation', 'Spain', 'United Kingdom', 'United States'],共12个国家。
单帧图片设置
各国颜色设置
用字典为每个国家设置16进制的颜色。
#为各国设置颜色
colors = dict(zip(country,['#CCFFFF','#CCFFCC','#FF3366','#99FFFF','#CCFF99','#FFFF99',
'#99CCCC','#FF6666','#CCCCFF','#FFCCFF','#FFCCCC','#FFCC99']))
绘图函数
此绘图函数包括数据选取,数据处理,添加标注以及横纵坐标、网格线、标题等的设置
fig, ax = plt.subplots(figsize=(15, 8))
def draw_barchart(year):
dff = (df[['Country Name','Country Code',year]].sort_values(by=year, ascending=False).head(10))
dff=dff[::-1]
#为作图方便将数值除以10^13
dff[year]=dff[year]/10**13
ax.clear()
ax.barh(dff['Country Name'], dff[year],color=[colors[x] for x in dff['Country Name']])
dx = dff[year].max() / 200
#添加标注
for i, (value, name) in enumerate(zip(dff[year], dff['Country Name'])):
#enumerate枚举对象,一个索引序列,同时列出数据和数据下标
ax.text(value-dx,i,name,size=12,weight=600, ha='right', va='bottom') #国家名称
ax.text(value-dx, i-0.25,value,size=10,color='#444444', ha='right', va='baseline') # GDP值/10^13
#添加年份
ax.text(1, 0.4, year, transform=ax.transAxes, color='#777777', size=46, ha='right', weight=800)
#添加指标
ax.text(0, 1.06, 'GDP (constant 2010 US$)ⅹ10^13', transform=ax.transAxes, size=12, color='#777777')
#横坐标保持两位小数,位于上方,颜色以及字体大小
#ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
ax.xaxis.set_ticks_position('top')
ax.tick_params(axis='x', colors='#777777', labelsize=12)
#去除纵坐标
ax.set_yticks([])
#设置自动缩放
ax.margins(0, 0.01)
#设置网格线
ax.grid(which='major', axis='x', linestyle='-')
#网格线置地
ax.set_axisbelow(True)
#标题
ax.text(0, 1.12, 'GDP rankings of countries in the world from 1990 to 2018',
transform=ax.transAxes, size=24, weight=600, ha='left')
#右下角标注
ax.text(1, 0, 'by Anran', transform=ax.transAxes, ha='right',
color='#777777', bbox=dict(facecolor='white', alpha=0.8, edgecolor='white'))
#去除外边框
plt.box(False)
draw_barchart('2018')
此时得到的图片如下所示:
动画制作
这里我们用到matplotlib.animation 中的 FuncAnimation反复调用上文写好的draw_barchart()函数,frames即为draw_barchart的参数。
fig, ax = plt.subplots(figsize=(15, 8))
animator = animation.FuncAnimation(fig, draw_barchart, frames=['1990','2000','2010','2011','2012','2013','2014','2015','2016','2017','2018'])
HTML(animator.to_jshtml())
此时就能得到我们的动图啦,还可以用animator.save('GDP.gif')保存为gif,保存视频animator.to_html5_video()需要ffmpeg。