超火动态价格面积图:手把手教你!

2019-12-17 17:03:16 浏览数 (1)

前言

近日,公众号推出了一篇名为《超火动态排序图:代码不到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。

0 人点赞