前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >超酷炫,百行Python代码制作动态曲线图

超酷炫,百行Python代码制作动态曲线图

作者头像
lyhue1991
发布2021-06-15 10:03:00
9390
发布2021-06-15 10:03:00
举报
文章被收录于专栏:Python与算法之美

先上图

再上视频:

最后上代码:

代码语言:javascript
复制
import numpy as np 
import pandas as pd 
import matplotlib as mpl 
from matplotlib import pyplot as plt 
import matplotlib.animation as  animation 

cmap = [
'#2E91E5',
'#1CA71C',
'#DA16FF',
'#B68100',
'#EB663B',
'#00A08B',
'#FC0080',
'#6C7C32',
'#862A16',
'#620042',
'#DA60CA',
'#0D2A63']*100

mpl.rcParams['animation.writer'] = 'html'

def line_chart_race(df,filename=None,title = "",figsize = (6.5,3.5),dpi = 144,duration = 0.5):
    
    assert "date" in df.columns, "df should with a column date!"
    assert filename is None or filename.endswith(".html"), "filename should like *.html!"

    fig,ax = plt.subplots(figsize=figsize,dpi=dpi)

    ax.set_facecolor("0.9")
   
    # 调整spines
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.spines["left"].set_visible(False)
    ax.spines["bottom"].set_visible(False)

    def plot_frame(date):
        dfdata = df.loc[df["date"]<=date,:]
        dfdata.index = dfdata["date"]
        idx = range(len(dfdata))

        ax.clear() 
        cols = [name for name in dfdata.columns if name!="date"]
        for i,col in enumerate(cols):

            ax.plot(idx,dfdata[col],color = cmap[i],lw = 4)
            px,py = idx[-1],dfdata[col].iloc[-1]
            ax.scatter(px,py,color = cmap[i],edgecolor = "black",
                      s = 200,lw = 2.5,zorder = 4)

            ax.annotate(col+":\n"+str(py),xy = (px,py),  xycoords = "data",
                       xytext = (10,2),fontweight = "bold",color = cmap[i], textcoords = "offset points")

        # 调整绘图范围
        xlim = (0,len(df))
        ax.set_xlim(xmin = xlim[0]-(xlim[1]-xlim[0])/10,xmax = xlim[1]+(xlim[1]-xlim[0])/10)
        values = df[[x for x in df.columns if x!="date"]].values
        ylim = (values.min(),values.max())
        ax.set_ylim(ymin = ylim[0]-(ylim[1]-ylim[0])/10,ymax = ylim[1]+(ylim[1]-ylim[0])/10)


        # 设置xticks
        n = len(df)
        ticks_num = 12
        delta = int(np.ceil(n/ticks_num)) 
        ticks = list(range(0,n,delta)) 
        dates =  df["date"].tolist()
        ticklabels =[dates[i] for i in ticks]
        ax.set_xticks(ticks)
        ax.set_xticklabels(ticklabels)
        
        ax.tick_params(bottom = False,left = False,labelsize = 8,direction = "in",length = 2)

        # 添加辅助元素
        s = dfdata["date"].iloc[-1]
        ax.text(0.5, 0.5, s, va="center", ha="center",alpha=0.3, size = 50,transform = ax.transAxes)
        ax.grid(axis = "x",color="white",lw=1,ls = "-")
        ax.set_title(title,color = "black",fontsize = 12)
        
    line_animation = animation.FuncAnimation(fig,plot_frame,frames = df["date"],interval = int(duration*1000))
    if filename is None:
        try:
            from IPython.display import HTML
            return HTML(line_animation.to_jshtml())
        except ImportError:
            pass
    else:
        line_animation.save(filename)
        return filename
    
dfdata = pd.read_csv('Pop_data.csv')
dfdata = dfdata.rename({"year":"date"},axis = 1)
for col in dfdata.columns:
    if col!="date":
        dfdata.loc[:,col] = np.round(dfdata.loc[:,col]/1e8,4)
dfdata.set_index(dfdata["date"])

html_file = "population_race.html"
html = line_chart_race(dfdata,html_file,title="Population Line Race")
html

主要思路是设计plot_frame绘图函数绘制逐桢图片,然后用matplotlib.animation构建动画,如果有需要,还可以导出成gif和mp4。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 算法美食屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档