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

  • Post author:
  • Post category:python


在之前的一篇文章当中,小编当时分享了如何用

Python

当中的

gif

模块来制作

gif

格式的图表,


厉害了,用Python绘制动态可视化图表,并保存成gif格式

今天小编再给大家来介绍一种制作

gif

格式图表的新方法,调用的是

matplotlib

的相关模块,其中的步骤与方法也是相当地简单易懂。

下载和导入数据库

我们这次用到的数据集是

bokeh

模块自带的数据集,通过下面这一行代码直接就可以下载

import bokeh
bokeh.sampledata.download()

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

from bokeh.sampledata.population import data
import numpy as np

data = filter_loc('United States of America')
data.head()

output

a99dbf19ef1eb3c3abde802e6687f327.png

先绘制若干张静态的图表

我们可以先绘制若干张静态的图表,然后将这几张图表合成一张

gif

格式的动图即可,代码如下

import seaborn as sns
import matplotlib.pyplot as plt
import 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 < 2022]
years.sort()

for year in years:
    fig = make_plot(year)
    fig.savefig(f'{year}.jpeg',bbox_inches = 'tight')

output

959eb372bf3b700148a6a9699ba5d447.png

这样我们就生成了若干张静态的图表,然后集合成

gif

格式的图表几个,代码如下

import matplotlib.animation as animation
fig, 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

7e456a26c292282faa8caf02d821360d.gif

还有另外一种思路

可能看到这儿,有人会觉得上面提到的方法稍显麻烦,毕竟我们需要先生成数十张静态的图表,要是电脑的磁盘空间有点紧张的话,或者还没有这样的一个地方来存放这数十张的图表。于是乎就会疑问道,是不是可以一步到位的来。

当然也是可以的,例如我们打算绘制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

9f29701ed9c0bd6289e6c71f7f7e5a97.png

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

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

84b3df748ebcfa72fa772f81b99ccbb7.gif

这样就可以一步到位生成

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

1c262a710012dd7c63e2814d8c4d375b.gif

想要获取源码的童鞋可以在公众号后台回复【

20220504


NO.


1

往期推荐

Historical articles


【优质好文】详谈国内爬虫开发人员的未来


【优质原创】分享几个Sklearn模块中不为人知又超级好用的API函数


【优质原创】介绍一个效率爆表的探索性数据分析插件


【原创内容】介绍一款进阶版的Pandas数据分析神器:Polars

分享、收藏、点赞、在看安排一下?

5dd11a92e2bc3a4ebd1f1d6b206214e3.gif

ced4bd01d9082dd97c1c1138f927e6b5.gif

c12673bc1894aaeed05cdc0027b1a37a.gif

ed862a3c6f0171cc3adb3029fcadf33f.gif



版权声明:本文为weixin_43373042原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。