近日,公众号推出了一篇名为《超火动态排序图:代码不到40行,手把手教你!》的文章,反向十分强烈。各大公众号进行的了转载,知乎也是有400 的点赞。
具体来说,这种图可以叫:Bar Chart Race,有什么国家GDP的、某某沉浮史等等。
今天EasyCharts博主张杰为我们带来了关于动态价格变化面积图的NB操作。下面就让我们赶紧看看吧!同时也祝张杰的新书大卖!
本文来源即将出版的新书《Python数据可视化之美》之动态图表的绘制。
正文
我们使用2013年-2019年比特币的价格数据绘制面积图动画,其HTML交互效果页面如下图所示,包括2013年04月28日起每天的开盘、最高、最低和收盘的价格。
具体实现代码
我们先导入数据集'BTC_price_history.csv',然后将date列转换成日期型数据。我们选择一天的最高和最低价的均值作为这一天比特币的价格Price。其具体代码如下:
代码语言:javascript复制df = pd.read_csv('BTC_price_history.csv')
df['date']=[datetime.strptime(d, '%Y/%m/%d').date() for d in df['date']]
df['price']=(df['high'] df['low'])/2
df.head(5)
我们设置图表每次展示Span_Date=180天的比特币价格数据,所以得到180天的数据集df_temp后,如果使用plt.fill_between()函数可以实现红色填充的面积图,如下图所示;如果使用plt.bar()函数可以实现Spectral_r颜色映射的面积图,如图下图b所示。代码如下:
代码语言:javascript复制def draw_areachart(Num_Date):
Span_Date=180
ax.clear()
if Num_Date<Span_Date:
df_temp=df.loc[0:Num_Date,:]
df_span=df.loc[0:Span_Date,:]
plt.fill_between(df_temp.date.values, y1=df_temp.price.values, y2=0,alpha=0.75, facecolor='r', linewidth=1,edgecolor ='none',zorder=1)
plt.plot(df_temp.date, df_temp.price, color='k',zorder=2)
plt.scatter(df_temp.date.values[-1], df_temp.price.values[-1], color='white',s=150,edgecolor ='k',linewidth=2,zorder=3)
plt.text(df_temp.date.values[-1], df_temp.price.values[-1]*1.18,s=np.round(df_temp.price.values[-1],1),size=10,ha='center', va='top')
plt.ylim(0, df_span.price.max()*1.68)
plt.xlim(df_span.date.values[0], df_span.date.values[-1])
plt.xticks(ticks=df_span.date.values[0:Span_Date 1:30],labels=df_span.date.values[0:Span_Date 1:30],rotation=0,fontsize=9)
else:
df_temp=df.loc[Num_Date-Span_Date:Num_Date,:]
plt.fill_between(df_temp.date.values[:-2], y1=df_temp.price.values[:-2], y2=0,alpha=0.75, facecolor='r', linewidth=1,edgecolor ='none',zorder=1)
plt.plot(df_temp.date[:-2], df_temp.price[:-2], color='k',zorder=2)
plt.scatter(df_temp.date.values[-4], df_temp.price.values[-4], color='white',s=150,edgecolor ='k',linewidth=2,zorder=3)
plt.text(df_temp.date.values[-1], df_temp.price.values[-1]*1.18,s=np.round(df_temp.price.values[-1],1),size=10,ha='center', va='top')
plt.ylim(0, df_temp.price.max()*1.68)
plt.xlim(df_temp.date.values[0], df_temp.date.values[-1])
plt.xticks(ticks=df_temp.date.values[0:Span_Date 1:30],labels=df_temp.date.values[0:Span_Date 1:30],rotation=0,fontsize=9)
plt.margins(x=0.2)
ax.spines['top'].set_color('none') # 设置上‘脊梁’为红色
ax.spines['right'].set_color('none') # 设置上‘脊梁’为无色
ax.spines['left'].set_color('none') # 设置上‘脊梁’为无色
plt.grid(axis="y",c=(217/256,217/256,217/256),linewidth=1) #设置网格线
plt.text(0.01, 0.95,"BTC平均价格($)",transform=ax.transAxes, size=10, weight='light', ha='left')
ax.text(-0.07, 1.03, '2013年到2019年的比特币BTC价格变化情况',transform=ax.transAxes, size=17, weight='light', ha='left')
fig, ax = plt.subplots(figsize=(6,4), dpi=100)
plt.subplots_adjust(top=1,bottom=0.1,left=0.1,right=0.9,hspace=0,wspace=0)
draw_areachart(180)
a
b
我们将上面的静态面积图代码整合成函数。当开始的日期天数据绘制面积图;当开始的日期≥时,就选择截止到当前日期的天数据绘制面积图。使用函数绘制的不同日期的面积图如图所示。
不同日期Num_Date的面积图,Num_Date=60
不同日期Num_Date的面积图,Num_Date=150
使用matplotlib包的animation.FuncAnimation()函数,调用draw_areachart(Num_Date)函数,其中输入的参数Num_Date = np.arange(0,df.shape[0],1),最后使用Ipython包的HTML()函数将动画转换成HTML页面的形式演示,其动画不同日期下的演示效果如图下图所示。
代码语言:javascript复制import matplotlib.animation as animation
from IPython.display import HTML
fig, ax = plt.subplots(figsize=(6,4), dpi=100)
plt.subplots_adjust(left=0.12, right=0.98, top=0.85, bottom=0.1,hspace=0,wspace=0)
animator = animation.FuncAnimation(fig, draw_areachart, frames=np.arange(0,df.shape[0],1),interval=100)#
HTML(animator.to_jshtml())
面积图动画不同时间下的演示效果
但是由于动画默认的最大体积为20971520.0 bytes,所以图11-4-10只生成了2013年04月-2014年07月数据绘制的面积图动画。如果需要调整生成的动画最大体积,需要更改参数animation.embed_limit。
matplotlib包和plotnine包都可以实现动态数据的可视化演示。其中,在matplotlib包中:函数FuncAnimation(fig,func,frames,init_func,interval,blit)是绘制动图的主要函数,其参数如下:
1、fig 表示绘制动图的画布名称(figure);
2、func为自定义绘图函数,如draw_barchart()函数;
3、frames为动画长度,一次循环包含的帧数,在函数运行时,其值会传递给函数draw_barchart (year)的形参“year”;
4、init_func为自定义开始帧,即初始化函数init,可省略;
5、interval表示更新频率,计量单位为ms;
6、blit表示选择更新所有点,还是仅更新产生变化的点,应选择为True,但mac用户应选择False,否则无法显示。
另外,也可以使用animator.save(‘animation.gif’)或者animator.save(‘animation.mp4)导出gif或者mp4格式的动画。但是如果要导出mp4,需要先安装已经安装ffmpeg 或者mencoder。