4

用Python做了一个广东疫情新增病例动态视频

 1 year ago
source link: https://www.pkslow.com/archives/python-covid-19-guangdong
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

最近广东疫情实在是太严重了,特别是广州。作为南大门,人口流动太大,又毗邻港澳,防疫任务太重。从11月以来,就发展极其迅猛。疫情也给大家的生活带来了诸多不便,我有许多同事和朋友都居家隔离了。

时代的尘埃落在个体身上,都是灾难。

为了对疫情了解更多,我用Python写了个小程序,来生成一个新增病例的变化视频,且记录一下这个无聊的过程吧。

2 数据准备

为了获得准确的第一手数据,我是关注了健康广东这个公众号,每天早上可以看到最新的数据。同时在广东省卫健委的网站也可以获取。

接着会把数据记录在Excel表格里,方面查看。11月以来数据如下:

注:新增 = 新增确诊 + 新增无症状

日期广东确诊广州确诊广东无症状广州无症状广东新增广州新增
11月1日239190458289697479
11月2日10673298253404326
11月3日6950356323425373
11月4日187142470430657572
11月5日160111669635829746
11月6日133661330125914631325
11月7日1851221882181320671935
11月8日1981142330226325282377
11月9日197912611254628082637
11月10日2001252507243027072555
11月11日2892252461235827502583
11月12日3232592996292133193180
11月13日2471893541346437883653
11月14日2191893941387641604065
11月15日1731475047497752205124
11月16日1951586215613864106296
11月17日3072758576848688838761
11月18日3212559110898994319244
11月19日3552698535844488908713
11月20日2812008381823486628434
11月21日3842968101788584858181
11月22日3472538241795785888210
11月23日3532357951773583047970
11月24日5494287505719280547620
11月25日3952577584726779797524

3 读取数据

因为要用Python展示,即做数据可视化(数据可视化的工具很多,不一定要用Python),所以需要用Python读取Excel中的数据。我使用的是库pyexcel。代码如下:

def load_data():
    records = p.get_records(file_name="covid-19.xlsx")
    print(records)
    data_x = []
    data_y1 = []
    data_y2 = []
    for record in records[1:]:
        dt = excel_to_datatime(record['-1'])
        data_x.append(dt)
        data_y1.append(record['-6'])
        data_y2.append(record['-7'])
    return data_x, data_y1, data_y2

其中covid-19.xlsx就是Excel文件名。而-1, -6, -7分别是对应的日期,和最后两列,Debug的时候定位的,暂时没空深究。

3.1 Excel日期的问题

Excel日期是用一个数字来表示的,所以需要把这个数值转化成Python的日期类型,具体代码如下:

def excel_to_datatime(excel_date):
    dt = datetime.fromordinal(datetime(1900, 1, 1).toordinal() + excel_date - 2)
    return dt

同时为了格式化输出日期,新增了个函数,没啥特别的:

def datetime_to_str(dt, pattern):
    return pattern.format(dt.month, dt.day)

4 Python数据可视化

Python做数据可视化的库可太多了,我选择的是matplotlib,一方面是因为它用的多,资料也多;另一方面是我大学用过Matlab,两者很像,省去一些学习时间成本。

为了简便,打算就画个曲线变化图就行了,所以横轴为日期,纵轴为新增数。画个简单的图代码如下:

# plot
fig, ax = plt.subplots(figsize=(4, 3), dpi=120)
ax.plot(data_x, data_y1, linewidth=2.0, color='red')
ax.plot(data_x, data_y2, linewidth=2.0, color='blue')
plt.show()

红色是广东新增,蓝色是广州新增:

python-covid-19-Guangdong.pic1.png

把数据标在曲线上:

for i, v in enumerate(data_y1):
    ax.text(data_x[i], v + 300, v, ha='center', color='red', fontsize=8)

for i, v in enumerate(data_y2):
    ax.text(data_x[i], v - 300, v, ha='center', color='blue', fontsize=8)

可以看到,3000到6000,再到8000的变化是极快的:

python-covid-19-Guangdong.pic2.png

后面还有许多细节优化,就不一一讲解了。

5 转化视频

首先要明白,视频的本质还是图片,只是把图片放快了而已。所以,可以画图,就有办法做视频。好在matplotlib也提供了制作动画的函数,直接调用即可。需要调用的是animation.FuncAnimation这个方法。我们要提供初始化函数,还有如何制作每一帧画面的函数,就可以制作视频了。

初始化就直接给个空就行:

def init():
    line1.set_data([], [])
    line2.set_data([], [])
    return line1, line2, text1, text2, text_gd, text_gz, text_date

每一帧的函数如下:

def animate(i):
    print('Processing {} for {}'.format(i, data_x[i]))
    x = range(i + 2)
    x = x[1:]
    line1.set_data(x, data_y1[:i + 1])
    line2.set_data(x, data_y2[:i + 1])
    text1 = ax.text(i + 1, data_y1[i] + 150, data_y1[i], ha='center', color='red', fontsize=8)
    text2 = ax.text(i + 1, data_y2[i] - 150, data_y2[i], ha='center', color='blue', fontsize=8)
    text_gd.set_text('广东新增:' + str(data_y1[i]))
    text_gz.set_text('广州新增:' + str(data_y2[i]))
    text_date.set_text(datetime_to_str(data_x[i], '2022年{}月{}日'))
    plt.scatter(x, data_y1[:i + 1], color='bisque')
    plt.scatter(x, data_y2[:i + 1], color='cyan')
    return line1, line2, text1, text2, text_gd, text_gz, text_date

核心是的两条曲线:line1, line2,每次动态的改变它的数据,就会重画;

text1, text2是新增数,标在曲线上的;

scatter函数是标点,显眼一点;

text_gd, text_gz, text_date在左上角动态显示变化的日期和数据。

图片大体效果如下:

python-covid-19-Guangdong.pic3.png

最后,我们要将一帧一帧整合成视频,使用以下函数:

plt.rcParams['animation.ffmpeg_path'] = '/Users/larry/Software/ffmpeg/ffmpeg'
anim.save('covid-19-Guangdong.mp4', fps=1, extra_args=['-vcodec', 'libx264'])

注意:这里需要用到软件ffmpeg,要指定你所安装的位置。这个软件可以直接从这里下载:https://evermeet.cx/ffmpeg/

最终视频效果如下:

愿大家健康快乐!

代码请看GitHub: https://github.com/LarryDpk/pkslow-samples/tree/master/python/src/main/python/covid-19-Guangdong


References:

How to Animate Line Plots Using Matplotlib in Python

https://medium.com/intel-student-ambassadors/live-graph-simulation-using-python-matplotlib-and-pandas-30ea4e50f883

https://towardsdatascience.com/animations-with-matplotlib-d96375c5442c

Excel Date:

https://www.geeksforgeeks.org/python-convert-excel-serial-date-to-datetime/

https://www.geeksforgeeks.org/how-to-convert-a-python-datetime-datetime-to-excel-serial-date-number/

https://stackoverflow.com/questions/31359150/convert-date-from-excel-in-number-format-to-date-format-python

Example and Turorial:

Top 50 matplotlib Visualizations – The Master Plots (with full python code)

Matplotlib Animation Tutorial

Colors:

https://matplotlib.org/stable/gallery/color/named_colors.html


Code for all: GitHub

欢迎关注微信公众号<南瓜慢说>,将持续为你更新...

file

Recommendations:
Cloud Native
Terraform
Container: Docker/Kubernetes
Spring Boot / Spring Cloud
Https
如何制定切实可行的计划并好好执行


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK