一、python绘制动画图 python绘制动态图形是数据可视化更直观、更好看的一种方式,matplotlib工具包是常用的绘图工具,也可以用来绘制动态图形。本文介绍四种绘制动态图形的方法,包括生成图形的代码和动态图形演示示例。 用matplotlib工具包创建动画图有两种方法:使用pause()函数使用FuncAnimation()函数动画柱状图,使用FuncAnimation()函数 代码如下:frommatplotlibimportpyplotaspltfrommatplotlib。animationimportFuncAnimation,writersimportnumpyasnpfigplt。figure(figsize(7,5))axesfig。addsubplot(1,1,1)axes。setylim(0,300)palette〔blue,red,green,darkorange,maroon,black〕y1,y2,y3,y4,y5,y6〔〕,〔〕,〔〕,〔〕,〔〕,〔〕defanimationfunction(i):y1iy25iy33iy42iy56iy63iplt。xlabel(Country)plt。ylabel(GDPofCountry)plt。bar(〔India,China,Germany,USA,Canada,UK〕,〔y1,y2,y3,y4,y5,y6〕,colorpalette)plt。title(BarChartAnimation)animationFuncAnimation(fig,animationfunction,interval50)plt。show() 如下图: 横向柱状跑图(HorizontalBarChartRace),使用FuncAnimation()函数 以下代码是绘制世界1500年2018年主要城市人口变化横向柱状跑图,需要数据集文件citypopulations。csv评论区留言。 程序代码如下:importpandasaspdimportmatplotlib。pyplotaspltimportmatplotlib。tickerastickerfrommatplotlib。animationimportFuncAnimationdfpd。readcsv(citypopulations。csv,usecols〔name,group,year,value〕)colorsdict(zip(〔India,Europe,Asia,LatinAmerica,MiddleEast,NorthAmerica,Africa〕,〔adb0ff,ffb3ff,90d595,e48381,aafbff,f7bb5f,eafb50〕))grouplkdf。setindex(name)〔group〕。todict()defdrawbarchart(year):dffdf〔df〔year〕。eq(year)〕。sortvalues(byvalue,ascendingTrue)。tail(10)ax。clear()ax。barh(dff〔name〕,dff〔value〕,color〔colors〔grouplk〔x〕〕forxindff〔name〕〕)dxdff〔value〕。max()200fori,(value,name)inenumerate(zip(dff〔value〕,dff〔name〕)):ax。text(valuedx,i,name,size14,weight600,haright,vabottom)ax。text(valuedx,i。25,grouplk〔name〕,size10,color444444,haright,vabaseline)ax。text(valuedx,i,f{value:,。0f},size14,haleft,vacenter)polishedstylesax。text(1,0。4,year,transformax。transAxes,color777777,size46,haright,weight800)ax。text(0,1。06,Population(thousands),transformax。transAxes,size12,color777777)ax。xaxis。setmajorformatter(ticker。StrMethodFormatter({x:,。0f}))ax。xaxis。setticksposition(top)ax。tickparams(axisx,colors777777,labelsize12)ax。setyticks(〔〕)ax。margins(0,0。01)ax。grid(whichmajor,axisx,linestyle)ax。setaxisbelow(True)ax。text(0,1。12,Themostpopulouscitiesintheworldfrom1500to2018,transformax。transAxes,size24,weight600,haleft)ax。text(1,0,,transformax。transAxes,haright,color777777,bboxdict(facecolorwhite,alpha0。8,edgecolorwhite))plt。box(False)plt。show()fig,axplt。subplots(figsize(15,8))animatorFuncAnimation(fig,drawbarchart,framesrange(1990,2019))plt。show() 散点图动画,使用FuncAnimation()函数 在本例中,使用random数据和自定义函数animationfunc()frommatplotlibimportpyplotaspltfrommatplotlib。animationimportFuncAnimationimportrandomimportnumpyasnpx〔〕y〔〕colors〔〕figplt。figure(figsize(7,5))defanimationfunc(i):x。append(random。randint(0,100))y。append(random。randint(0,100))colors。append(np。random。rand(1))arearandom。randint(0,30)random。randint(0,30)plt。xlim(0,100)plt。ylim(0,100)plt。scatter(x,y,ccolors,sarea,alpha0。5)animationFuncAnimation(fig,animationfunc,interval100)plt。show() 如下图: 使用pause()函数绘制动态直线 matplotlib工具包的pyplot模块中有pause()函数,可用来设置时间间隔参数,达到绘制直线的动画效果。 代码如下:frommatplotlibimportpyplotaspltx〔〕y〔〕foriinrange(100):x。append(i)y。append(i)Mentionxandylimitstodefinetheirrangeplt。xlim(0,100)plt。ylim(0,100)Plotinggraphplt。plot(x,y,colorgreen)plt。pause(0。01)plt。show() 如下图: 使用FuncAnimation()绘制动态直线 FuncAnimation()函数本身并不能创建动画效果,而是通过生成一系列不同参数的图片来实现动画效果。 Syntax:FuncAnimation(figure,animationfunction,framesNone,initfuncNone,fargsNone,savecountNone,,cacheframedataTrue,kwargs) 在这个实例代码中,使用FuncAnimation函数创建一条直线的简单动画效果,只需要调整参数即刻。frommatplotlibimportpyplotaspltfrommatplotlib。animationimportFuncAnimationimportnumpyasnpx〔〕y〔〕figure,axplt。subplots()Settinglimitsforxandyaxisax。setxlim(0,100)ax。setylim(0,12)Sinceplottingasinglegraphline,ax。plot(0,0)defanimationfunction(i):x。append(i15)y。append(i)line。setxdata(x)line。setydata(y)returnline,animationFuncAnimation(figure,funcanimationfunction,framesnp。arange(0,10,0。1),interval10)plt。show() 如下图: 二、如何把python绘制的动态图形保存为gif文件或视频 使用Matplotlib中的matplotlib。animation方法可以绘制更好看、更有吸引力的动画图形,那如何把这种动画图形保存为Gif动画文件或视频文件呢?本文简述与之相关的方法。把python程序中绘制的动画图形保存为视频格式或gif格式文件,以便播放或发送给其他人,或者插入找文档或网页中。本文分两部分,先介绍python程序绘制简单的动态图形或动画,然后再介绍如何把绘制的动态图形或动画保存为gif格式文件或视频文件。 先用Matplotlib。animation类中的函数FuncAnimation创建动态图和动画,如动态折线、柱状图动画,另外还需要使用figure函数和animation函数,这些都是python使用matplotlib绘制图形时常用的方法。1。创建动态折线图 1)绘制动态折线图,代码如下:importrandomimportmatplotlibimportmatplotlib。pyplotaspltfrommatplotlib。animationimportFuncAnimationfigplt。figure(figsize(15,15))x,y〔〕,〔〕indexcount()defanimate(i):x。append(next(index))y。append(random。randint(2,20))plt。style。use(ggplot)plt。plot(x,y)aniFuncAnimation(fig,animate,interval300)plt。show() 结果如图1: 主要代码行说明: 以上代码块中aniFuncAnimation(fig,animate,interval300)这一行中,FuncAnimation()有三个参数: 1)fig,表示图形参数 指容纳plot图形的对象,需要创建该对象,或者调用matplotlib。pyplot。gcf()函数,表示获得当前图形; 2)animate自定义函数 这是FuncAnimation中的动画自定义函数,要想获得动画图形就要把该参数设定为animate,图形就会根据数据持续更新,注意创建图形和数据更新缺一不可。 3)画面间隔参数interval 该参数指定画面的更新速度,单位是毫秒。interval1000表示该函数运行动画函数,并且每秒钟更新一次。 以上代码块中plt。style。use(ggplot)这一行,指定动画图形的风格为ggplot,要想了解更多的图形风格,可使用以下代码:importmatplotlib。pyplotaspltprint(plt。style。available) 输入结果如下:bmhclassicdarkbackgroundfastfivethirtyeightggplotgrayscaleseabornbrightseaborncolorblindseaborndarkpaletteseaborndarkseaborndarkgridseaborndeepseabornmutedseabornnotebookseabornpaperseabornpastelseabornposterseaborntalkseabornticksseabornwhiteseabornwhitegridseabornSolarizeLight2tableaucolorblind10classictest 上述代码块输出的图形结果中,两个数轴都是不固定的,这与MatplotlibAxesSetting有关,plot函数中也没有定义线的颜色。2。创建动画图形 代码如下:importmatplotlib。pyplotaspltfrommatplotlib。animationimportFuncAnimationmatplotlibqtfigplt。figure(figsize(6,4))axesfig。addsubplot(1,1,1)plt。title(DynamicAxes)y1〔random。randint(10,10)(i1。6)(random。randint(9,12))foriinrange(0,280,2)〕trange(len(y1))x,y〔〕,〔〕defanimate(i):x。append(t〔i〕)y。append((y1〔i〕))plt。xlim(i30,i3)axes。setylim(y1〔i〕100,y1〔i〕100)plt。plot(x,y,scaleyTrue,scalexTrue,colorred)animFuncAnimation(fig,animate,interval100) 输出结果如图2: 图2动态数轴动画 保存动态图形 保存Matplotlib绘制的动画可能会出现一些小故障。下面介绍一下常用的选项和参数,既可以节省保存动画所需的时间,又可以尽可能地减少故障;可以把python代码生成的动画保存为个人需要的格式,如gif、mp4、avi、mov等文件格式,这取决于保存时选择对应的参数。保存为GIF文件图1,代码如下:frd:animation。gifwritergifanimation。PillowWriter(fps30)anim。save(f,writerwritergif) 这段代码中,常用的选项有ImageMagick和PillowWriter。 对于windows操作系统来说,使用ImageMagick方法一般要先安装相关程序包,并且在保存动画为GIF文件时,建议使用WriteInstance,还是比较复杂;如果是Unix操作系统,ImageMagick一般情况下都已经安装了,使用ImageMagick方法就方便。因此,建议windows用户使用PillowWriter方法。 定义gif图形的帧数: 修改FuncAnimation函数中的savecount参数的值,设定GIF文件的帧数,默认为100帧,代码如下:animanimation。FuncAnimation(figure,funcupdatefigure,fargs(barrects,iteration),framesgenerator,interval100,repeatTrue,savecount1500) 示例代码中,把GIF文件的帧数修改为1500帧。保存为视频文件 把调用matplotlib的方法生成的动画保存为视频文件,需要ffmpeg。exe安装程序,可到官网下载,如下图: 特别注意,安装后要把该运行程序的路径ffmpegbinffmpeg。exe添加到环境变量中,此路径一定要正确并且一定是指向可执行文件,而不仅仅是该文件所在的文件夹。在生成动画的python程序块中要加入以下代码行:importmatplotlibasmplmpl。rcParams〔animation。ffmpegpath〕rC:UsersxxDesktopffmpegbinffmpeg。exe 接下来,把matplotlib绘制的动画保存为mp4格式的视频文件,代码如下:frd:animation。mp4writervideoanimation。FFMpegWriter(fps60)anim。save(f,writerwritervideo) 定义视频的尺寸: 视频的尺寸就是用matplotlib工具包绘制图形的窗口大小,调整对应窗口的大小即刻,示例代码如下:plt。subplots(figsize(12,8)) 三、使用matplotlib绘制动画 在python编程中,用matplotlib绘图工具包绘制动画图形。动画是数据图形化的一种方法,视觉冲击力很强,给人留下了深刻的印象。动画图形或者可交互图形和静态图形相比,对人的诱惑力更强。像股票数据,气象数据,季节性和趋势这样的数据,用动画来表示会让人更容易明白。matplotlib库的主要特征有很多后台渲图工具组成它可以重新生成任何形式的绘图(只需要略做修改)该工具包历史悠久,比较成熟matplotlib和MATLAB绘图可以转换 然而,matplotlib库也有一些缺点:matplotlib有一个必要的API,这类接口一般比较冗长有时一些默认的绘图风格比较粗陋对web图形和交互图形的支持不足绘制大规模数据和复杂数据的图形比较慢matplotlib的animation基类和使用条件 matplotlib绘制动画图形就是使用animation基类的方法,它提供了构建动画功能的基本框架,使用的主要接口有两个:FuncAnimation:通过重复调用函数func绘制动画ArtistAnimation:使用一组固定的Artist对象实现动画效果 这两个接口相比之下,使用FuncAnimation最方便。 使用matplotlib绘制动画需要安装必要的工具包和程序:需要安装numpy和matplotlib工具包把程序生成的动画保存为mp4格式或gif格式文件,需要安装ffmpeg或imagemagick。 更详细的内容可阅读文章《如何把python绘制的动态图形保存为gif文件或视频》实例1:移动的正弦曲线 代码如下:importnumpyasnpfrommatplotlibimportpyplotaspltfrommatplotlib。animationimportFuncAnimationplt。style。use(seabornpastel)figplt。figure()axplt。axes(xlim(0,4),ylim(2,2))line,ax。plot(〔〕,〔〕,lw3)definit():line。setdata(〔〕,〔〕)returnline,defanimate(i):xnp。linspace(0,4,1000)ynp。sin(2np。pi(x0。01i))line。setdata(x,y)returnline,animFuncAnimation(fig,animate,initfuncinit,frames200,interval20,blitTrue)anim。save(sinewave。gif,writerimagemagick) 输出的图形结果如下图所示: 实例2:螺旋线动画 代码如下:importmatplotlib。pyplotaspltimportmatplotlib。animationasanimationimportnumpyasnpplt。style。use(darkbackground)figplt。figure()axplt。axes(xlim(50,50),ylim(50,50))line,ax。plot(〔〕,〔〕,lw2)初始化函数definit():创建空的plotframeline。setdata(〔〕,〔〕)returnline,存储x轴和y轴坐标值的列表xdata,ydata〔〕,〔〕定义动画函数defanimate(i):参数tt0。1i根据x和y的值绘制图形xtnp。sin(t)ytnp。cos(t)把新的x轴和y轴的值追加到列表xdata。append(x)ydata。append(y)line。setdata(xdata,ydata)returnline,制定图形的标题plt。title(Creatingagrowingcoilwithmatplotlib!)隐藏x轴上的数据标识plt。axis(off)调用动画函数animanimation。FuncAnimation(fig,animate,initfuncinit,frames500,interval20,blitTrue)把动画保存为gif文件anim。save(coil。gif,writerimagemagick) 输出结果如下图所示: 实例3:动画实时更新 绘制股票行情数据、传感器数据等实时图形就需要实时更新动画。 代码如下:importmatplotlib。pyplotaspltimportmatplotlib。animationasanimationfigplt。figure()创建子图ax1fig。addsubplot(1,1,1)defanimate(i):dataopen(stock。txt,r)。read()linesdata。split()xs〔〕ys〔〕forlineinlines:x,yline。split(,)Delimiteriscommaxs。append(float(x))ys。append(float(y))ax1。clear()ax1。plot(xs,ys)plt。xlabel(Date)plt。ylabel(Price)plt。title(Livegraphwithmatplotlib)anianimation。FuncAnimation(fig,animate,interval1000)plt。show() 输出结果如下图所示: 实例4:3D动画 代码如下:frommpltoolkits。mplot3dimportAxes3Dimportmatplotlib。pyplotaspltimportpandasaspdimportseabornassns获取数据urlhttps:pythongraphgallery。comwpcontentuploadsvolcano。csvdatapd。readcsv(url)数据转换dfdata。unstack()。resetindex()df。columns〔X,Y,Z〕转换列名称df〔X〕pd。Categorical(df〔X〕)df〔X〕df〔X〕。cat。codes以20个不同的角度,绘制20个图形forangleinrange(70,210,2):绘制图形figplt。figure()axfig。gca(projection3d)ax。plottrisurf(df〔Y〕,df〔X〕,df〔Z〕,cmapplt。cm。viridis,linewidth0。2)ax。viewinit(30,angle)filenameVolcanoVolcanostepstr(angle)。pngplt。savefig(filename,dpi96)plt。gca() 以上代码创建多个PNG格式文件,要使用ImageMagick把这些图片转换为动画,即在命令行窗口输入下命令:convertdelay10Volcano。pnganimatedvolcano。gif 输出结果如下图: 实例5:使用Celluloid工具包绘制动画 Celluloid工具包简化了用matplotlib绘制动画的过程,该工具包只创建一个matplotlib的figure对象和camera对象,然后创建的每一帧画面都重复使用这个figure和camera对象,就像是用照相机在抓拍图形。最后,用所有抓拍的画面帧就构成了动画。 安装Celluloid工具包:pipinstallcelluloid 使用celluloid工具包的绘图实例如下: 实例51,代码如下:frommatplotlibimportpyplotaspltfromcelluloidimportCamerafigplt。figure()cameraCamera(fig)foriinrange(10):plt。plot(〔i〕10)camera。snap()animationcamera。animate()animation。save(celluloidminimal。gif,writerimagemagick) 输出结果如下图: 实例52:子图,代码如下:importnumpyasnpfrommatplotlibimportpyplotaspltfromcelluloidimportCamerafig,axesplt。subplots(2)cameraCamera(fig)tnp。linspace(0,2np。pi,128,endpointFalse)foriint:axes〔0〕。plot(t,np。sin(ti),colorblue)axes〔1〕。plot(t,np。sin(ti),colorblue)camera。snap()animationcamera。animate()animation。save(celluloidsubplots。gif,writerimagemagick) 输出结果如下图: 实例53:图例,代码如下:importmatplotlibfrommatplotlibimportpyplotaspltfromcelluloidimportCamerafigplt。figure()cameraCamera(fig)foriinrange(20):tplt。plot(range(i,i5))plt。legend(t,〔fline{i}〕)camera。snap()animationcamera。animate()animation。save(celluloidlegends。gif,writerimagemagick) 输出结果如下图: 四、Python2D3D动画案例 本文以九个ETF基金行情数据为例,绘制出交易这九个基金的收益变化(行情数据有随机数生成)。如果想观察哪只基金的收益高于或低于沪深300ETF,就可以从2D3D的动画图上看出来。下面分四部分来讲述。导入必要的工具包importnumpyasnpimportpandasaspdimportcsvfromcsvimportwriter绘图importmatplotlib。pyplotaspltfrommatplotlibimportanimation,rcfrommatplotlib。cmimportgetcmapfrommpltoolkits。mplot3dimportAxes3Dfrommatplotlib。fontmanagerimportFontPropertiesfrommatplotlib。collectionsimportLineCollectionfrommatplotlib。colorsimportListedColormapfrommpltoolkits。mplot3d。art3dimportLine3DCollectionplt。rcParams〔font。sansserif〕〔SimHei〕plt。rcParams〔axes。unicodeminus〕Falseimportmatplotlibasmplmpl。rcParams〔animation。ffmpegpath〕rC:ffmpegbinffmpeg。exe设置动画类型rc(animation,htmlhtml5)导入数据 用随机数生成九只ETF基金的行情价格数据indexreturnsnp。random。normal(loc1e4,scale5e3,size(783,9))indexreturnsnp。vstack((np。zeros(shape(1,9))100,indexreturns))累计收益indexpricesnp。cumprod(1indexreturns,axis0)选择时间窗口window261indexesrollingnp。zeros(shape(indexprices。shape〔0〕window,9))生成滚动收益foriinrange(window,indexprices。shape〔0〕,1):indexesrolling〔iwindow〕(indexprices〔i〕indexprices〔iwindow〕)1构成dataframe数据indexpd。daterange(20190101,periodsindexprices。shape〔0〕window,freqB)columns〔智能汽车515250,新能源车515030,半导体512480,银行512800,沪深300510300,创新药159992,光伏515790,信息技术159939,食品饮料515170〕indexesrollingpd。DataFrame(indexesrolling,indexindex,columnscolumns)2D动画创建2D动画的规格以及格式,即指定该动画图形的大小,颜色,图例等内容。 代码如下:创建图形fig,axesplt。subplots(1,2,figsize(18,6),gridspeckw{widthratios:〔。9,。1〕})fig。patch。setalpha(1)设置:右边的图形不可见,只更新左边部分axes〔1〕。axis(off)axaxes〔0〕获取cmapcmapgetcmap(RdYlGn)数据切分currentsliceindexesrolling。values〔:261,:〕indexnamesindexesrolling。columnsindexdatesindexesrolling。index保存各ETF基金数据的列表lines〔〕foriinrange(currentslice。shape〔1〕):获取坐标xnp。array(np。arange(currentslice。shape〔0〕))ynp。array(currentslice〔:,i〕)绘制不同颜色的点和线段pointsnp。array(〔x,y〕)。T。reshape(1,1,2)segmentsnp。concatenate(〔points〔:1〕,points〔1:〕〕,axis1)指定连续值,映射数据点的颜色normplt。Normalize(0。19,0。19)lcLineCollection(segments,cmapcmap,normnorm)设置颜色值lc。setarray(y)lc。setlinewidth(2)lc。setcolor(cmap(y〔1〕2。50。5))lc。setlabel(indexnames〔i〕)lines。append(ax。addcollection(lc))添加背景的网格ax。legend(loccenterright,bboxtoanchor(1。2,0。5),fancyboxTrue,facecolor(。95,。95,。95,1),framealpha1,shadowFalse,frameonTrue,ncol1,columnspacing0,prop{family:SimHei})ax。yaxis。grid(colorgray,linestyledashed)ax。xaxis。grid(colorgray,linestyledashed)ax。setxlim(0,currentslice。shape〔0〕1)ax。setylim(0。39,0。39)ax。setyticklabels(〔{:。0}。format(val)forvalinax。getyticks()〕)ax。setylabel(滚动收益1年)ax。setxlabel(日期)ax。setxticklabels(〔indexdates〔int(val)〕。strftime(my)forvalinax。getxticks()〕)ax。setfacecolor((0,0,0,1。0))背景色ax。setfacecolor((0。05,0。05,0。65,1))演示图形plt。show() 演示图形如下: 2。定义更新以上2D图形的函数 代码如下:defupdatelines2D(num,data,columns,dates,cmap,lines,ax):获得切分数据currentslicedata〔num:261num,:〕currentdatesdates〔num:261num〕foriinrange(currentslice。shape〔1〕):获取坐标值xnp。array(np。arange(currentslice。shape〔0〕))ynp。array(currentslice〔:,i〕)绘制不同颜色的点和线段pointsnp。array(〔x,y〕)。T。reshape(1,1,2)segmentsnp。concatenate(〔points〔:1〕,points〔1:〕〕,axis1)指定连续值,映射数据点的颜色normplt。Normalize(0。22,0。22)lines〔i〕。setsegments(segments)lines〔i〕。setarray(y)lines〔i〕。setcolor(cmap(y〔1〕2。50。5))lines〔i〕。setcolor(cmap(y〔1〕2。50。5))动态更新数据和标识ax。setxticklabels(〔dates〔int(val)num〕。strftime(my)forvalinax。getxticks()〔:1〕〕〔〕)ax。legend(loccenterright,bboxtoanchor(1。2,0。5),fancyboxTrue,facecolor(。95,。95,。95,1),framealpha1,shadowFalse,frameonTrue,ncol1,columnspacing0,prop{family:SimHei})returnlines初始化图形的各行的数据definitlines2D():forlineinlines:line。setarray(〔〕)returnlines 3。创建2D动画 代码如下:lineanianimation。FuncAnimation(figfig,funcupdatelines2D,frames30,framesindexesrolling。shape〔0〕261,initfuncinitlines2D,fargs(indexesrolling。values,indexesrolling。columns,indexesrolling。index,cmap,lines,ax),interval75,blitTrue)演示2D动画lineani 演示结果如下图: 4。保存动画为GIF格式 代码如下:演示数据的变化progresscallbacklambdai,n:print(Savingframe{:。0}。format(in))ifint((in)100)100elseNone保存动画lineani。save(。2Danimation。gif,writerimagemagick,fps14,dpi80,codech264,bitrate2048,progresscallbackprogresscallback)3D动画创建3D动画的规格以及格式,即指定该动画图形的大小,颜色,图例等内容。 代码如下:创建图形figplt。figure(figsize(14。4,9))axfig。addsubplot(111,projection3d)fig。patch。setalpha(1)获得cmap的值cmapgetcmap(RdYlGn)切分数据currentsliceindexesrolling。values〔:261,:〕indexnamesindexesrolling。columnsindexdatesindexesrolling。index保存各ETF基金数据的线的列表lines〔〕foriinrange(currentslice。shape〔1〕):获取坐标值xnp。array(np。arange(currentslice。shape〔0〕))ynp。tile(i,currentslice。shape〔0〕)znp。array(currentslice〔:,i〕)绘制不同颜色的点和线段pointsnp。array(〔x,y,z〕)。T。reshape(1,1,3)segmentsnp。concatenate(〔points〔:1〕,points〔1:〕〕,axis1)指定连续值,映射数据点的颜色normplt。Normalize(0。19,0。19)lcLine3DCollection(segments,cmapcmap,normnorm,zordercurrentslice。shape〔1〕i)动态更新数据和标识lc。setarray(z)lc。setlinewidth(2)lc。setcolor(cmap(z〔1〕2。50。5))lc。setlabel(indexnames〔i〕)lines。append(ax。addcollection(lc))添加动画背景的网格ax。legend(loccenterright,bboxtoanchor(1。1,0。46),fancyboxTrue,facecolor(。95,。95,。95,1),framealpha1,shadowFalse,frameonTrue,ncol1,columnspacing0,prop{family:SimHei})ax。setzlabel(滚动收益1Y,labelpad10)ax。setzlim(0。39,0。39)ax。setzticklabels(〔3{:。0}。format(val)forvalinax。getzticks()〕,fontdict{verticalalignment:center,horizontalalignment:center})ax。setxlabel(Date,labelpad30)ax。setxlim(0,currentslice。shape〔0〕1)ax。setxticklabels(〔indexdates〔int(val)〕。strftime(my)forvalinax。getxticks()〔:1〕〕〔〕,rotation0,fontdict{verticalalignment:top,horizontalalignment:center})ax。setyticks(np。arange(currentslice。shape〔1〕))ax。setyticklabels(〔indexnames〔i〕foriinrange(currentslice。shape〔1〕)〕,rotation15,fontdict{verticalalignment:center,horizontalalignment:left})ax。wxaxis。setpanecolor((0,0,0,1。0))ax。wyaxis。setpanecolor((0,0,0,1。0))ax。wzaxis。setpanecolor((0,0,0,1。0))ax。wxaxis。setpanecolor((0。05,0。05,0。65,1))ax。setfacecolor((0。05,0。05,0。65,1))ax。wyaxis。setpanecolor((0。05,0。05,0。65,1))ax。wzaxis。setpanecolor((0。05,0。05,0。65,1))ax。viewinit(25,60)xscale1。8yscale1zscale1scalenp。diag(〔xscale,yscale,zscale,1。0〕)scalescale(1。0scale。max())scale〔3,3〕1。0defshortproj():returnnp。dot(Axes3D。getproj(ax),scale)ax。getprojshortprojfig。subplotsadjust(left0,right1,bottom0,top1)输出动画plt。show() 输出结果如下图所示: 2。定义更新以上图形的函数 代码如下:defupdatelines3D(num,data,columns,dates,cmap,lines,ax):切分数据currentslicedata〔num:261num,:〕currentdatesdates〔num:261num〕foriinrange(currentslice。shape〔1〕):获取坐标值xnp。arange(currentslice。shape〔0〕)ynp。tile(i,currentslice。shape〔0〕)znp。array(currentslice〔:,i〕)绘制不同颜色的点和线段pointsnp。array(〔x,y,z〕)。T。reshape(1,1,3)segmentsnp。concatenate(〔points〔:1〕,points〔1:〕〕,axis1)指定连续值,映射数据点的颜色normplt。Normalize(0。19,0。19)lines〔i〕。setsegments(segments)lines〔i〕。setarray(z)lines〔i〕。setcolor(cmap(z〔1〕2。50。5))动态更新数据和标识ax。setxticklabels(〔dates〔int(val)num〕。strftime(my)forvalinax。getxticks()〔:1〕〕〔〕,rotation0,fontdict{verticalalignment:top,horizontalalignment:center})ax。legend(loccenterright,bboxtoanchor(1。1,0。46),fancyboxTrue,facecolor(。95,。95,。95,1),framealpha1,shadowFalse,frameonTrue,ncol1,columnspacing0,prop{family:SimHei})returnlinesdefinitlines3D():forlineinlines:line。setarray(〔〕)returnlines 3。创建3D动画 代码如下:lineanianimation。FuncAnimation(figfig,funcupdatelines3D,frames30,framesindexesrolling。shape〔0〕261,initfuncinitlines3D,fargs(indexesrolling。values,indexesrolling。columns,indexesrolling。index,cmap,lines,ax),interval75,blitTrue)演示3D动画lineani 演示结果如下图所示: 4。保存3D动画为GIF格式progresscallbacklambdai,n:print(Savingframe{:。0}。format(in))ifint((in)100)100elseNonesavetheanimationlineani。save(。3Danimation。gif,writerimagemagick,fps14,dpi80,codech264,bitrate2048,progresscallbackprogresscallback)3Dmesh动画创建3Dmesh动画的规格以及格式,即指定该动画图形的大小,颜色,图例等内容。 代码如下:创建图形figplt。figure(figsize(14。4,9))axfig。addsubplot(111,projection3d)fig。patch。setalpha(1)获取cmap的值cmapgetcmap(RdYlGn)切分数据currentsliceindexesrolling。values〔:261,:〕currentsliceindexesrolling。values〔:int(2612),:〕indexnamesindexesrolling。columnsindexdatesindexesrolling。index保存各ETF基金数据的线的列表lines〔〕foriinrange(currentslice。shape〔1〕):获取坐标值xnp。array(np。arange(currentslice。shape〔0〕))ynp。tile(i,currentslice。shape〔0〕)znp。array(currentslice〔:,i〕)绘制不同颜色的点和线段pointsnp。array(〔x,y,z〕)。T。reshape(1,1,3)segmentsnp。concatenate(〔points〔:1〕,points〔1:〕〕,axis1)指定连续值,映射数据点的颜色normplt。Normalize(0。19,0。19)lcLine3DCollection(segments,cmapcmap,normnorm,zordercurrentslice。shape〔1〕i)设定颜色值lc。setarray(z)lc。setlinewidth(2)lc。setcolor(cmap(z〔1〕2。50。5))lc。setlabel(indexnames〔i〕)lines。append(ax。addcollection(lc))保存mesh线的列表meshlines〔〕forjinrange(currentslice。shape〔0〕):ifj10:获取坐标值xnp。tile(j,currentslice。shape〔1〕)ynp。arange(currentslice。shape〔1〕)znp。array(currentslice〔j,:〕)绘制不同颜色的点和线段pointsnp。array(〔x,y,z〕)。T。reshape(1,1,3)segmentsnp。concatenate(〔points〔:1〕,points〔1:〕〕,axis1)指定连续值,映射数据点的颜色normplt。Normalize(0。19,0。19)lcLine3DCollection(segments,cmapcmap,normnorm)设定颜色值lc。setarray(z)lc。setlinewidth(2)meshlines。append(ax。addcollection(lc))添加mesh动画的背景网格ax。legend(loccenterright,bboxtoanchor(1。1,0。46),fancyboxTrue,facecolor(。95,。95,。95,1),framealpha1,shadowFalse,frameonTrue,ncol1,columnspacing0,prop{family:SimHei})ax。setzlabel(RollingEquity1Y,labelpad10)ax。setzlim(0。39,0。39)ax。setzticklabels(〔3{:。0}。format(val)forvalinax。getzticks()〕,fontdict{verticalalignment:center,horizontalalignment:center})ax。setxlabel(Date,labelpad30)ax。setxlim(0,currentslice。shape〔0〕1)ax。setxticklabels(〔indexdates〔int(val)〕。strftime(my)forvalinax。getxticks()〔:1〕〕〔〕,rotation0,fontdict{verticalalignment:top,horizontalalignment:center})ax。setyticks(np。arange(currentslice。shape〔1〕))ax。setyticklabels(〔indexnames〔i〕foriinrange(currentslice。shape〔1〕)〕,rotation15,fontdict{verticalalignment:center,horizontalalignment:left})ax。wxaxis。setpanecolor((0。05,0。05,0。65,1))ax。wyaxis。setpanecolor((0。05,0。05,0。65,1))ax。wzaxis。setpanecolor((0。05,0。05,0。65,1))(0。05,0。05,0。65,1)ax。viewinit(25,60)xscale1。8yscale1zscale1scalenp。diag(〔xscale,yscale,zscale,1。0〕)scalescale(1。0scale。max())scale〔3,3〕1。0defshortproj():returnnp。dot(Axes3D。getproj(ax),scale)ax。getprojshortprojfig。subplotsadjust(left0,right1,bottom0,top1)输出图形plt。show() 输出结果如下图所示: 2。定义更新以上图形的函数 代码如下:defupdatemeshlines3D(num,data,columns,dates,cmap,lines,meshlines,ax):切分数据currentslicedata〔num:int(2612)num,:〕foriinrange(currentslice。shape〔1〕):获取坐标值xnp。arange(currentslice。shape〔0〕)ynp。tile(i,currentslice。shape〔0〕)znp。array(currentslice〔:,i〕)绘制不同颜色的点和线段pointsnp。array(〔x,y,z〕)。T。reshape(1,1,3)segmentsnp。concatenate(〔points〔:1〕,points〔1:〕〕,axis1)指定连续值,映射数据点的颜色normplt。Normalize(0。19,0。19)lines〔i〕。setsegments(segments)lines〔i〕。setarray(z)lines〔i〕。setcolor(cmap(z〔1〕2。50。5))通过计数检查当前的mesh线counter0forjinrange(currentslice。shape〔0〕):ifj10:获取坐标值xnp。tile(j,currentslice。shape〔1〕)ynp。arange(currentslice。shape〔1〕)znp。array(currentslice〔j,:〕)绘制不同颜色的点和线段pointsnp。array(〔x,y,z〕)。T。reshape(1,1,3)segmentsnp。concatenate(〔points〔:1〕,points〔1:〕〕,axis1)设定mesh线的颜色值normplt。Normalize(0。22,0。22)meshlines〔counter〕。setsegments(segments)meshlines〔counter〕。setarray(z)counter1动态更新数据和标识ax。setxticklabels(〔dates〔int(val)num〕。strftime(my)forvalinax。getxticks()〔:1〕〕〔〕,rotation0,fontdict{verticalalignment:top,horizontalalignment:center})ax。legend(loccenterright,bboxtoanchor(1。1,0。46),fancyboxTrue,facecolor(。95,。95,。95,1),framealpha1,shadowFalse,frameonTrue,ncol1,columnspacing0,prop{family:SimHei})returnlinesdefinitmeshlines3D():forlineinlines:line。setarray(〔〕)returnlines 3。创建3Dmesh动画 代码如下:lineanianimation。FuncAnimation(figfig,funcupdatemeshlines3D,frames30,framesindexesrolling。shape〔0〕int(2612),initfuncinitmeshlines3D,fargs(indexesrolling。values,indexesrolling。columns,indexesrolling。index,cmap,lines,meshlines,ax),interval100,blitTrue)演示动画lineani 演示结果如下图所示: