COVID-19数据分析实战:用Python绘制动态排名视频

简介: COVID-19数据分析实战:用Python绘制动态排名视频

前言


第一篇第二篇第三篇我们对数据进行了重新布局,布局后的数据结构方便我们进行柱状图可视化以及弹道分析。


今天我们来学习使用该数据集执着更酷炫的动态排名视频。

先看效果:


640.gif


一如既往,直奔代码。


640.png


准备数据源


数据源就是我们一直分析的COVID19 data 数据,可以去kaggle 下载。


导入我们所需的库,相比于之前的文章,我们本次分析会用到animation模块,重点是里面会提供FuncAnimation 类,帮助我们实现动态图。


# coding: utf-8
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.animation as animation
from datetime import datetime, timedelta
import numpy as np


pandas 读取数据,这是每篇分析的第一步操作。简单处理数据,采用groupby 函数将一些国家的各个省份信息合并成该国家的总和。前一篇文章有详细介绍,此处不再说明。


# read data
covid19_data_file = 'data/COVID_19_data.csv'
covid19_data_df = pd.read_csv(covid19_data_file)
# handle the countries data
df_country = covid19_data_df.groupby(
    ['ObservationDate', 'Country/Region']).sum()
df_country.reset_index(inplace=True)


动态视频思路-FuncAnimation


大家都知道,视频就是一堆堆图像(或者称为帧 frame)在时间轴上连续起来形成的。所以我们的思路也很简单,制作一个画面,改变画面的内容,重复制作这个画面。


matplotlib 已经有这个类:FuncAnimation,它用来重复调用一个函数进行画图。我们来研究一下它的主要参数,更详细的请参考官方文档。


class matplotlib.animation.FuncAnimation(fig, func, frames=None, init_func=None, fargs=None, save_count=None, *, cache_frame_data=True, **kwargs)[source]¶


其中主要的参数:


  • fig:就是matplotlib的Figure 对象。
  • func:就是需要重复调用的函数。对于我们这个案例来说,需要重复的事情就是“画(水平)柱状图”。所以我们需要定义个画水平柱状图的函数。这也是本文的重点。
  • frames:就是可迭代的对象,假如我们赋值为整数n,就是用range(n)来创造迭代对象
  • init_func:类似于func,如果你的第一帧画面需要调用不同的函数,可选此参数
  • fargs:func 函数的其他参数(除去frames 必须作为第一个位置参数)
  • 其他参数:略


为了调用这个函数,我们需要准备好各个参数。


  • 采用subplots 创建Figure 对象,命名为fig。
  • 调用datetime,设置需要动态显示的起止日期,并且计算出delta 时间。该值我们将作为frames 参数传递给FuncAnimation函数。
  • 剩下就是重中之重,func 函数以及fargs 参数


fig, ax = plt.subplots(figsize=(15, 8))
start_date = datetime(2020, 1, 22)
end_date = datetime(2020, 5, 13)
dates_delta = (end_date - start_date).days


每一帧画面的绘制函数func


先上代码,再做解释。


def mini_bar_chart_frame(
        delta,
        df=None,
        start_date=None,
        date_col=None,
        cat_col=None,
        observe_col=None,
        top_k=10,
        ax=None):
    if start_date is None:
        start_date = datetime(2020, 2, 22)
    date_show = timedelta(days=delta) + start_date
    date_str = date_show.strftime('%m/%d/%Y')
    top_k_df = df[df[date_col].eq(date_str)].sort_values(
        by=observe_col, ascending=False).head(top_k)
    ax.clear()
    # plot horizon bar
    ax.barh(
        top_k_df[cat_col],
        top_k_df[observe_col],
        log=False)
    ax.invert_yaxis()  # to make the biggest in the top
    #dx = np.log(top_k_df[observe_col].max()) / 200
    for i, (value, name) in enumerate(
            zip(top_k_df[observe_col], top_k_df[cat_col])):
        ax.text(
            value - 20,
            i,
            name,
            size=10,
            weight=600,
            ha='right',
            va='center')
        ax.text(
            value + 0.1,
            i,
            f'{value:,.0f}',
            size=10,
            ha='left',
            va='center')
    ax.text(
        1,
        0.1,
        date_str,
        transform=ax.transAxes,
        size=40,
        ha='right',
        weight=800)
    ax.set_yticks([])  # we have label on the top of bar


640.png


代码中我们主要实现一下内容:


  • 整理数据,选出每天top10的国家,并且降序排列
  • 绘制barh,水平绘制时,需要反转y轴,使得最大值排在第一位。也就是上图中第1部分内容绘制完毕
  • 添加国家名称以及对应的确诊数据。也就是上图中第2 和第3部分内容
  • 添加大写的日期,放在右下角,也就是图中第4部分
  • 里面还有一些细节,比如取消掉y轴的标签


函数准备好了,下面我们就将函数的对应的参数传递给FuncAnimation。


fargs = (df_country,
         start_date,
         'ObservationDate',
         'Country/Region',
         'Confirmed',
         10,
         ax)
animator = animation.FuncAnimation(
    fig,
    mini_bar_chart_frame,
    frames=dates_delta,
    fargs=fargs,
    interval=1000,
    repeat=False)


我们也可以使用以下代码将其保存为本地mp4格式。


writer = animation.writers['ffmpeg']
writer = writer(fps=1)
animator.save('mini_covid_bar_race.mp4', writer=writer)


我们看一下上述代码的输出结果,这里我将视频转成gif以做演示。基本效果已经成型,应该算是很经典的动态排名了。


640.png

来点更炫的(彩色+动态文字+xkcd)


彩色柱状图


给柱状图添加颜色,应该很好处理。barh 函数带有color 参数,这里仅仅需要注意传入的颜色需要是类数组的格式。小技巧:


  • 由于我们无法为所有的国家定义颜色,因此这里我们采用定义一个dict颜色集,里面定义主要国家的颜色,然后对于没有定义在dict中的国家,颜色采用默认。颜色代码的获取可以从很多网站查询和复制。


color_dict = {'Mainland China': '#e63946',
              'US': '#ff006e',
              'Italy': '#02c39a',
              'Span': '#f4a261',
              'UK': '#3a86ff',
              'Germany': '#370617',
              'France': '#3a86ff',
              'Japan': '#d8e2dc',
              'Iran': '#fec89a',
              'Russia': '#dc2f02'}
# barh 中的color 参数为:
# color=[
#                color_dict.get(
#                    x,
#                    "#f8edeb") for x in top_k_df[cat_col]],


添加动态文字


这里我添加了一些文字来给视频做注释。比如3月15日,中国捐给西班牙50万个口罩。


  • 之所以用英文,是因为最初这个视频是我放在facebook上给老外看的。
  • 第二个原因,是因为中文需要一些字体支持。

实现动态文字添加的思路很简单,就是ax.text 函数。实现方法类似于我们的国家标签以及确诊数的标签。


640.png


timeline_event = {
    '01/30/2020': 'WuHan declared lockdown.',
    '01/31/2020': 'Italian suspended all flights from China',
    '02/02/2020': 'Trump restricts on any foreigners from entering the U.S',
    '03/13/2020': 'China sent medical supplies to Italy',
    '03/15/2020': 'China donated 500,000 facemasks to Spain',
    '03/19/2020': 'USA suspended visa services worldwide.',
    '05/12/2020': 'America first(LOL).'
}


添加xkcd 效果


xkcd 是啥?只不过一个漫画名称而已,不好发音,也不是缩写。对于matplotlib 来说,xkcd 就指的类似于漫画的的效果。通俗讲就是“线条抖啊抖啊抖~~~~” 代码很简单就一行:


with plt.xkcd():
        把所有plt相关的代码放在这个with 里面


完整的func 函数


除了添加颜色,动态文字以及“抖啊抖”的效果,我们还做了一些细节处理,比如调整字体颜色,字号等小细节。


def xkcd_bar_chart_frame(
        delta,
        df=None,
        start_date=None,
        date_col=None,
        cat_col=None,
        observe_col=None,
        top_k=10,
        color_dict=None,
        ax=None):
    if start_date is None:
        start_date = datetime(2020, 2, 22)
    date_show = timedelta(days=delta) + start_date
    date_str = date_show.strftime('%m/%d/%Y')
    top_k_df = df[df[date_col].eq(date_str)].sort_values(
        by=observe_col, ascending=False).head(top_k)
    with plt.xkcd():
        ax.clear()
        # plot horizon bar
        ax.barh(
            top_k_df[cat_col],
            top_k_df[observe_col],
            color=[
                color_dict.get(
                    x,
                    "#f8edeb") for x in top_k_df[cat_col]],
            log=False,
            left=1)
        ax.invert_yaxis()  # to make the biggest in the top
        #dx = np.log(top_k_df[observe_col].max()) / 200
        for i, (value, name) in enumerate(
                zip(top_k_df[observe_col], top_k_df[cat_col])):
            ax.text(
                value - 20,
                i,
                name,
                size=10,
                weight=600,
                ha='right',
                va='center')
            ax.text(
                value + 0.1,
                i,
                f'{value:,.0f}',
                size=10,
                ha='left',
                va='center')
        ax.text(
            1,
            0.1,
            date_str,
            transform=ax.transAxes,
            color='#f8edeb',
            size=40,
            ha='right',
            weight=800)
        ax.text(
            0.5,
            1.1,
            'Covid-19',
            transform=ax.transAxes,
            size=14,
            color='#f8edeb')
        ax.text(
            0.2,
            0.05,
            timeline_event.get(date_str, ''),
            transform=ax.transAxes,
            size=20,
            color='#06d6a0')
        ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
        ax.xaxis.set_ticks_position('top')
        ax.tick_params(axis='x', colors='#777777', labelsize=12)
        ax.set_yticks([])
        ax.margins(0, 0.01)
        ax.grid(which='major', axis='x', linestyle='-')
        ax.set_axisbelow(True)
        plt.box(False)


重新调用这个新的func来制作动画。


fargs = (df_country,
         start_date,
         'ObservationDate',
         'Country/Region',
         'Confirmed',
         10,
         color_dict,
         ax)
animator = animation.FuncAnimation(
    fig,
    xkcd_bar_chart_frame,
    frames=dates_delta,
    fargs=fargs,
    interval=1000,
    repeat=False)


最后我们来看一下我们更新后的动画效果。ps. 眼看着中国从top10中消失,眼看着America First。


640.png


Tips


保存为MP4格式需要电脑安装ffmep 编码/解码器,安装好的ffmpeg_path需要添加到matplotlibrc 参数下。


# add ffmpeg path to matplotlibrc
plt.rcParams['animation.ffmpeg_path'] = r'your_path\ffmpeg-20200323-ba698a2-win64-static\ffmpeg-20200323-ba698a2-win64-static\bin\ffmpeg.exe'


总结


本文中我们继续使用covid19的数据来进行可视化分析。我们采用python 制作了酷炫的动态排名。定义的函数可以套用在其他数据集中用于制作动态排名。通过本文我们可以学会:


  • 如何制作动态排名(barh race) 图,以及保存为视频
  • 如何给bar 不同类别赋予不同的颜色
  • 如果给画面添加文字
  • 如何是画面显得“抖一抖”
相关文章
|
1月前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
271 7
|
1月前
|
数据采集 Web App开发 数据安全/隐私保护
实战:Python爬虫如何模拟登录与维持会话状态
实战:Python爬虫如何模拟登录与维持会话状态
|
1月前
|
传感器 运维 前端开发
Python离群值检测实战:使用distfit库实现基于分布拟合的异常检测
本文解析异常(anomaly)与新颖性(novelty)检测的本质差异,结合distfit库演示基于概率密度拟合的单变量无监督异常检测方法,涵盖全局、上下文与集体离群值识别,助力构建高可解释性模型。
298 10
Python离群值检测实战:使用distfit库实现基于分布拟合的异常检测
|
1月前
|
数据可视化 大数据 关系型数据库
基于python大数据技术的医疗数据分析与研究
在数字化时代,医疗数据呈爆炸式增长,涵盖患者信息、检查指标、生活方式等。大数据技术助力疾病预测、资源优化与智慧医疗发展,结合Python、MySQL与B/S架构,推动医疗系统高效实现。
|
1月前
|
数据采集 监控 数据库
Python异步编程实战:爬虫案例
🌟 蒋星熠Jaxonic,代码为舟的星际旅人。从回调地狱到async/await协程天堂,亲历Python异步编程演进。分享高性能爬虫、数据库异步操作、限流监控等实战经验,助你驾驭并发,在二进制星河中谱写极客诗篇。
Python异步编程实战:爬虫案例
|
1月前
|
存储 分布式计算 测试技术
Python学习之旅:从基础到实战第三章
总体来说,第三章是Python学习路程中的一个重要里程碑,它不仅加深了对基础概念的理解,还引入了更多高级特性,为后续的深入学习和实际应用打下坚实的基础。通过这一章的学习,读者应该能够更好地理解Python编程的核心概念,并准备好应对更复杂的编程挑战。
102 12
|
1月前
|
存储 数据采集 监控
Python文件操作全攻略:从基础到高级实战
本文系统讲解Python文件操作核心技巧,涵盖基础读写、指针控制、异常处理及大文件分块处理等实战场景。结合日志分析、CSV清洗等案例,助你高效掌握文本与二进制文件处理,提升程序健壮性与开发效率。(238字)
269 1
|
1月前
|
存储 Java 调度
Python定时任务实战:APScheduler从入门到精通
APScheduler是Python强大的定时任务框架,通过触发器、执行器、任务存储和调度器四大组件,灵活实现各类周期性任务。支持内存、数据库、Redis等持久化存储,适用于Web集成、数据抓取、邮件发送等场景,解决传统sleep循环的诸多缺陷,助力构建稳定可靠的自动化系统。(238字)
457 1
|
1月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
226 0
|
1月前
|
数据采集 自然语言处理 数据可视化
Python爬取B站视频评论区情感分析:从数据采集到价值挖掘
B站作为年轻人聚集地,评论蕴含丰富情感与趋势。本文详解如何用Python爬取评论,结合SnowNLP与jieba进行中文情感分析,并通过可视化挖掘用户情绪、消费意愿与内容反馈,助力精准运营与决策。
360 0

推荐镜像

更多
下一篇
oss云网关配置