PHP前端开发

用Python绘制超酷的gif动图,惊艳了所有人

百变鹏仔 1个月前 (01-21) #Python
文章标签 超酷

在之前的一篇文章当中,小编当时分享了如何用​​Python​​​当中的​​gif​​​模块来制作​​gif​​格式的图表,

厉害了,用Python绘制动态可视化图表,并保存成gif格式今天小编再给大家来介绍一种制作​​gif​​​格式图表的新方法,调用的是​​matplotlib​​的相关模块,其中的步骤与方法也是相当地简单易懂。

下载和导入数据库

我们这次用到的数据集是​​bokeh​​模块自带的数据集,通过下面这一行代码直接就可以下载

import bokehbokeh.sampledata.download()

然后导入后面要用到的数据集,我们挑选的是指定国家的1950年至今不同年龄阶段的人口所占比重的数据

from bokeh.sampledata.population import dataimport numpy as npdata = filter_loc('United States of America')data.head()

output

先绘制若干张静态的图表

我们可以先绘制若干张静态的图表,然后将这几张图表合成一张​​gif​​格式的动图即可,代码如下

import seaborn as snsimport matplotlib.pyplot as pltimport matplotlib.patheffects as fx# 绘制图表的函数def make_plot(year):        # 根据年份来筛选出数据    df = data[data.Year == year]            # 制作图表    fig, (ax1, ax2) = plt.subplots(1, 2, sharey = True)    ax1.invert_xaxis()    fig.subplots_adjust(wspace = 0)         ax1.barh(df[df.Sex == 'Male'].AgeGrp, df[df.Sex == 'Male'].percent, label = 'Male')    ax2.barh(df[df.Sex == 'Female'].AgeGrp, df[df.Sex == 'Female'].percent, label = 'Female', color = 'C1')        country = df.Location.iloc[0]    if country == 'United States of America': country == 'US'            fig.suptitle(f'......')    fig.supxlabel('......')    fig.legend(bbox_to_anchor = (0.9, 0.88), loc = 'upper right')    ax1.set_ylabel('Age Groups')        return fig

我们自定义了一个绘制图表的函数,其中的参数是年份,逻辑很简单,我们是想根据年份来筛选出数据,然后根据筛选出的数据来绘制图表,每一年的图表不尽相同

years = [i for i in set(data.Year) if i <p>output</p><p style="text-align: center;"><img src="https://img.php.cn/upload/article/000/887/227/168318834842840.png" alt="用Python绘制超酷的gif动图,惊艳了所有人"></p><p>这样我们就生成了若干张静态的图表,然后集合成​​gif​​格式的图表几个,代码如下</p><pre class="brush:python;toolbar:false;">import matplotlib.animation as animationfig, ax = plt.subplots()ims = []for year in years:    im = ax.imshow(plt.imread(f'{year}.jpeg'), animated = True)    ims.append([im])ani = animation.ArtistAnimation(fig, ims, interval=600)ani.save('us_population.gif')

output

还有另外一种思路

可能看到这儿,有人会觉得上面提到的方法稍显麻烦,毕竟我们需要先生成数十张静态的图表,要是电脑的磁盘空间有点紧张的话,或者还没有这样的一个地方来存放这数十张的图表。于是乎就会疑问道,是不是可以一步到位的来。当然也是可以的,例如我们打算绘制1950年到2020年不同年龄阶段的人口比例分布图,首先第一步在于我们先要绘制1950年,也就是起始年,该年不同年龄阶段的人口比例分布图,代码如下

fig, (ax1, ax2) = plt.subplots(1, 2, sharey = True)   df = data[data.Year == 1955]y_pos = [i for i in range(len(df[df.Sex == 'Male']))]male = ax1.barh(y_pos, df[df.Sex == 'Male'].percent, label = 'Male',               tick_label = df[df.Sex == 'Male'].AgeGrp)female = ax2.barh(y_pos, df[df.Sex == 'Female'].percent, label = 'Female',                   color = 'C1', tick_label = df[df.Sex == 'Male'].AgeGrp)ax1.invert_xaxis()fig.suptitle('.......')fig.supxlabel('....... (%)')fig.legend(bbox_to_anchor = (0.9, 0.88), loc = 'upper right')ax1.set_ylabel('Age Groups')

output

然后我们自定义一个绘制图表的函数,其中参数为年份,目的在于通过年份来筛选出相对应的数据并且绘制出相对应的图表

def run(year):    # 通过年份来筛选出数据    df = data[data.Year == year]    # 针对不同地性别来绘制    total_pop = df.Value.sum()    df['percent'] = df.Value / total_pop * 100    male.remove()    y_pos = [i for i in range(len(df[df.Sex == 'Male']))]    male.patches = ax1.barh(y_pos, df[df.Sex == 'Male'].percent, label = 'Male',                      color = 'C0', tick_label = df[df.Sex == 'Male'].AgeGrp)    female.remove()    female.patches = ax2.barh(y_pos, df[df.Sex == 'Female'].percent, label = 'Female',                                  color = 'C1', tick_label = df[df.Sex == 'Female'].AgeGrp)    text.set_text(year)    return male#, female

然后我们调用​​animation.FuncAnimation()​​方法,

ani = animation.FuncAnimation(fig, run, years, blit = True, repeat = True,                               interval = 600)ani.save('文件名.gif')

output

这样就可以一步到位生成​​gif​​格式的图表,避免生成数十张繁多地静态图片了。

将若干张​​gif​​动图放置在一张大图当中

最后我们可以将若干张​​gif​​动图放置在一张大的图表当中,代码如下

import matplotlib.animation as animation# 创建一个新的画布fig, (ax, ax2, ax3) = plt.subplots(1, 3, figsize = (10, 3))ims = []for year in years:    im = ax.imshow(plt.imread(f'文件1{year}.jpeg'), animated = True)    im2 = ax2.imshow(plt.imread(f'文件2{year}.jpeg'), animated = True)    im3 = ax3.imshow(plt.imread(f'文件3{year}.jpeg'), animated = True)    ims.append([im, im2, im3])ani = animation.ArtistAnimation(fig, ims, interval=600)ani.save('comparison.gif')

output