基于PyEcharts的COVID-19疫情可视化分析

2020-04-27 14:17:52 浏览数 (1)

查看本案例完整的数据、代码和报告请登录数据酷客(cookdata.cn)案例板块。

视频内容

1. 世界各国家现存确诊人数地图

将国家或地区的数值信息映射到地图上,通过颜色变化来表示数值的大小或范围。颜色地图适合带有地理位置信息的数据的展现,将颜色和地图相结合,直观显示数据的地理分布,通过颜色深浅容易判断数值的大小。下图显示的是截止到4月6日,中国各省市现有确诊人数地图,每个省市区域被赋予一种颜色,通过查看左下角的图例可以明确每种颜色对应的数值范围。我们可以看到图例中的颜色由下至上依次从浅到深,数值范围也相应地由小到大。通过地图可以非常直观地看到各省市现存确诊人数的多少,比如湖北的现存确诊还有几百人,北京、上海、广东等地由于境外输入病例的增加,还存在不少的现有确诊病例,安徽、广西、青海等地现有确诊病例已经清零。

在了解了颜色地图的一些基本情况后,我们利用pyecharts绘制截止到4月4日,世界现存确诊人数地图,首先我们导入4月4日当天的全球疫情数据:

代码语言:javascript复制
# 读取数据
import pandas as pd

world_data = pd.read_csv('./input/today_world_2020_04_04.csv')

接下来我们导入pyecharts库以及绘图需要的相关类:

代码语言:javascript复制
import pyecharts
# 调整配置项
import pyecharts.options as opts
# Map类用于绘制地图
from pyecharts.charts import Map

首先我们利用各国家的累计确诊人数减去累计治愈和累计死亡人数得到现存确诊人数,作为新的一列特征添加到数据中:

代码语言:javascript复制
world_data['today_storeConfirm'] = world_data['total_confirm'] - world_data['total_heal'] - world_data['total_dead']

利用Map类绘制世界地图时,需要输入各国家的英文名称和对应的数值,但我们的数据中国家的名称是中文,所以我们首先要将中文名称转换为英文名称:

代码语言:javascript复制
world_data.head()

我们载入国家中英文对照表,使用Series类的replace方法将各国家对应的中文名称替换成英文名称:

代码语言:javascript复制
contry_name = pd.read_csv('./input/county_china_english.csv', encoding='GB2312')
contry_name.head()
代码语言:javascript复制
world_data['eg_name'] = world_data['name'].replace(contry_name['中文'].values ,contry_name['英文'].values)
world_data['eg_name'].head()

提取出我们需要的数据,保存成一个嵌套列表的形式:

代码语言:javascript复制
heatmap_data = world_data[['eg_name','today_storeConfirm']].values.tolist()
heatmap_data[:10]

接下来我们开始绘图,首先初始化类对象Map,并调用add方法添加绘图基本配置:

代码语言:javascript复制
map_ = Map().add(series_name = "现存确诊人数", # 设置提示框标签
                 data_pair = heatmap_data, # 输入数据
                 maptype = "world", # 设置地图类型为世界地图
                 is_map_symbol_show = False # 不显示标记点
                ) 

为保证图形更美观并且更易于观察,继续添加系列和全局配置项:

代码语言:javascript复制
# 设置系列配置项
map_.set_series_opts(label_opts=opts.LabelOpts(is_show=False))  # 不显示国家(标签)名称 
代码语言:javascript复制
# 设置全局配置项
map_.set_global_opts(title_opts = opts.TitleOpts(title="世界各国家现存确诊人数地图"), # 设置图标题
                     # 设置视觉映射配置项
                     visualmap_opts = opts.VisualMapOpts(pieces=[ # 自定义分组的分点和颜色
                                                               {"min": 10000,"color":"#800000"}, # 栗色
                                                               {"min": 5000, "max": 9999, "color":"#B22222"}, # 耐火砖
                                                               {"min": 999, "max": 4999,"color":"#CD5C5C"}, # 印度红
                                                               {"min": 100, "max": 999, "color":"#BC8F8F"}, # 玫瑰棕色
                                                               {"max": 99, "color":"#FFE4E1"}, # 薄雾玫瑰
                                                              ], 
                     is_piecewise = True))  # 显示分段式图例

调用render_notebook方法可以直接在jupyter notebook中渲染图形:

由上图可以看到,新冠肺炎疫情已经造成了全球大流行,世界上只有几个国家还没有受到新冠肺炎疫情的侵袭。在亚洲,伊朗现存确诊人数最多,中国由于发生疫情较早,防控措施到位以及对患者积极的治疗,现存确诊人数已大幅减少;在美洲,美国目前是世界上疫情最为严重的国家,现存确诊人数最多,这个数字还在随着每日新增确诊人数的增加而不断上升;欧洲是目前世界上疫情最为严重的大洲,以意大利和西班牙为首的几个主要国家都有大量的现存确诊病例,各个国家的医疗系统正面临巨大的压力。

2. 世界国家累计死亡人数玫瑰图

玫瑰图是一种二维极坐标统计图。玫瑰图与饼状图类似,饼状图各个扇形的半径相同,角度不同,角度表示每一部分占比的大小;玫瑰图各个扇形的半径和角度都不同,角度依然表示每一部分的占比大小,半径表示每一部分的数值大小。下图是一个特殊的玫瑰图,扇形角度一致,半径不同,可以很清楚观察到海外每个国家累计确诊人数的大小对比关系。下面我们通过绘制截止到4月4日,世界国家累计死亡人数玫瑰图,从另一角度分析世界国家的疫情严重程度。

首先筛选出累计死亡人数超过500人的世界国家,并按人数进行降序排序:

代码语言:javascript复制
need_data = world_data[['name','total_dead']][world_data['total_dead'] >500]
代码语言:javascript复制
rank = need_data[['name','total_dead']].sort_values(by='total_dead',ascending=False).values

接着导入Pie类并添加绘图的基本配置:

代码语言:javascript复制
from pyecharts.charts import Pie

pie = Pie().add("累计死亡人数", # 添加提示框标签
                rank, # 输入数据
                radius = ["20%", "80%"],  # 设置内半径和外半径
                center = ["60%", "60%"],  # 设置圆心位置
                rosetype = "radius")   # 玫瑰图模式,通过半径区分数值大小,角度大小表示占比

最后设置全局和系列配置项并绘制玫瑰图:

代码语言:javascript复制
pie.set_global_opts(title_opts = opts.TitleOpts(title="世界国家累计死亡人数玫瑰图",  # 设置图标题
                                                pos_right = '40%'),  # 图标题的位置
                    legend_opts = opts.LegendOpts( # 设置图例
                                                orient='vertical', # 垂直放置图例
                                                pos_right="85%", # 设置图例位置
                                                pos_top="15%"))

pie.set_series_opts(label_opts = opts.LabelOpts(formatter="{b} : {d}%")) # 设置标签文字形式为(国家:占比(%))

# 在notebook中进行渲染     
pie.render_notebook()

从图上可以看到前11名国家中欧洲占到了8席,意大利和西班牙的累计死亡人数排在前两位,已经破万,美国由于疫情的快速发展,累计死亡人数快速上升,来到第三位。目前意大利和西班牙的医疗系统不堪重负,医疗物资严重不足,并且有大量医务人员感染。相对而言美国的医疗救护能力更强,美国每10万人的ICU病床数达为34.7个,而意大利的数据是12.5个ICU床位/10万人,西班牙则更少,只有9.7个ICU床位/10万人,不到美国的三分之一,很多重症病人住不了院,没有呼吸机。

3. 3月美国单日新增确诊人数与股票指数涨跌幅折线图

3月,全球投资人经历了美股历史上最为动荡的一个月,10天经历了4次熔断。所谓熔断机制(Circuit Breaker),也叫自动停盘机制,是指当股指波幅达到规定的熔断点时,交易所为控制风险采取的暂停交易措施。折线图可以显示随时间而变化的连续数据,因此非常适合显示在相等时间间隔下数据的趋势,下图所示的是截止到4月6日,海外多国累计确诊人数折线图,可以直观地观察到海外国家的累计确诊人数在3月中旬后快速增长,特别是美国,几乎呈指数级增长上升。

我们从akshare上获取了3月份三只股票指数的涨跌幅数据,分别是纳斯达克综合指数(美国)、上证指数(中国)和日经225指数(日本),通过折线图可以观察美国疫情对美国股票乃至世界其它股票的影响。

首先我们读取从API上获取的股票指数数据,由于周末股市不开盘,所以只有22天的数据:

代码语言:javascript复制
stock = pd.read_csv('./input/stockindex.csv',encoding='GB2312')
stock

接着读取全球疫情历史数据:

代码语言:javascript复制
alltime_data = pd.read_csv('./input/alltime_world_2020_04_04.csv')

筛选出与股票开盘日期对应的美国单日新增确诊人数:

代码语言:javascript复制
import warnings
warnings.filterwarnings('ignore')
代码语言:javascript复制
alltime_us = alltime_data[alltime_data['name'] == '美国']
代码语言:javascript复制
use_data = alltime_us[alltime_data['date'].isin(stock['日期'].values)][['date','today_confirm']]

然后导入绘制折线图的Line类和绘制组合图形的Grid类:

代码语言:javascript复制
from pyecharts.charts import Line, Grid

定义美国单日新增确诊人数折线图的相关设置:

代码语言:javascript复制
l1 = Line().add_xaxis(# 配置x轴
                      xaxis_data = use_data['date'].values   # 输入x轴数据
                      )


l1.add_yaxis(# 配置y轴
             series_name = "单日新增人数",  # 设置图例名称
             y_axis = use_data['today_confirm'].values.tolist(),  # 输入y轴数据
             symbol_size = 10, # 设置点的大小
             label_opts = opts.LabelOpts(is_show=False), # 标签设置项:显示标签
             linestyle_opts = opts.LineStyleOpts(width=1.5, type_='dotted'), # 线条宽度和样式
             is_smooth = True, # 绘制平滑曲线
             )

# 设置全局配置项
l1.set_global_opts(title_opts = opts.TitleOpts(title = "3月美国单日新增人数与股票指数涨幅对比折线图", 
                                               pos_left = "center"), # 设置图标题和位置
                   axispointer_opts = opts.AxisPointerOpts(is_show = True, 
                                                           link = [{"xAxisIndex": "all"}]),  # 坐标轴指示器配置
                   # x轴配置项
                   xaxis_opts = opts.AxisOpts(type_ = "category",
                                              boundary_gap = True), # 坐标轴两边是否留白
                   # y轴配置项 
                   yaxis_opts = opts.AxisOpts(name = "单日新增人数"), # 轴标题
                   # 图例配置项
                   legend_opts = opts.LegendOpts(pos_left  ='7%') # 图例的位置
                   )

定义三支股票指数变化的折线图设置:

代码语言:javascript复制
l2 = Line().add_xaxis(xaxis_data = use_data['date'].values)

l2.add_yaxis(series_name = "上证指数",  
             y_axis = stock['SSEC'].values,  # 添加上证指数数据
             symbol_size = 10,
             label_opts = opts.LabelOpts(is_show = False),
             linestyle_opts = opts.LineStyleOpts(width = 1.5), # 设置线宽
             is_smooth = True)

l2.add_yaxis(series_name = "日经225指数",
             y_axis = stock['N225'].values,  # 添加日经225指数数据
             symbol_size = 10,
             label_opts = opts.LabelOpts(is_show = False),
             linestyle_opts = opts.LineStyleOpts(width = 1.5),
             is_smooth = True)

l2.add_yaxis(series_name = "纳斯达克综合指数",
             y_axis = stock['NASDAQ'].values, # 添加纳斯达克综合指数数据
             symbol_size = 10,
             label_opts = opts.LabelOpts(is_show = False),
             linestyle_opts = opts.LineStyleOpts(width = 1.5),
             is_smooth = True)

l2.set_global_opts(axispointer_opts = opts.AxisPointerOpts(  # 设置坐标轴指示器
                                                           is_show = True, 
                                                           link = [{"xAxisIndex": "all"}]),  # 对x轴所有索引进行联动

                   xaxis_opts = opts.AxisOpts(grid_index = 1,  # x轴开始的索引
                                             type_ = "category", # 类型
                                             boundary_gap = True,
                                             position = "top", # 坐标轴位置
                                             axisline_opts = opts.AxisLineOpts(is_on_zero=True)),  # x轴或y轴的轴线是否在另一个轴的0刻度上

                   yaxis_opts = opts.AxisOpts(is_inverse = False, name = "涨跌幅(%)",name_gap = 25), # 轴线设置
                   legend_opts = opts.LegendOpts(pos_bottom = '50%',pos_right = '70') # 图例设置
                   )

将两幅图按照上下位置进行组合:

代码语言:javascript复制
# 绘制组合图形
grid = Grid(init_opts = opts.InitOpts(width = "1024px", height = "768px")) # 设置图形的长和宽

grid.add(chart=l1,  # 添加第一个图表
         grid_opts = opts.GridOpts(pos_left = 50, pos_right = 50, height = "35%"))  # 直角坐标系网格配置项

grid.add(chart = l2, # 添加第二个图表
         grid_opts = opts.GridOpts(pos_left = 50, pos_right = 50, pos_top = "55%", height = "35%"))

# 利用notebook进行渲染
grid.render_notebook()

美国特朗普政府为了防止股市下跌,让美联储降息,极力的淡化疫情的危害,以至于在3月初每日新增的确诊人数没有大量增加。特朗普释放的利好消息根本没有解决股民对新冠疫情感到未知恐惧的问题,而错过防疫时间,让疫情在美国快速蔓延。因此美国股市一跌再跌,在3月9号、12号、16号和18号触发了四次熔断,而后又在熔断的第二天暴涨,美国股市的熔断同时也影响了另外的两只股票指数,上证指数和日经225指数也有不同幅度的下跌。

4. 3月世界国家累计确诊人数动态条形图

条形图由一些长度不等的横向长方形组成,以长方形的长度来表示数据,易于比较各组数据之间的差别。比如下图显示的是截止到4月6日,海外主要疫情国家-每百万人确诊数条形图,可以明显看出不同国家确诊人数的差距。

动态图表是目前非常流行的一种可视化方法,可以按照时间序列动态展示条形图数据的变化。接下来我们利用Matplotlib绘制3月世界国家累计确诊人数的动态条形图,来分析最近这一个月来疫情较为严重的国家累计确诊人数的变化。

我们首先挑选出疫情最为严重的10个国家,并筛选出这些国家的历史疫情数据:

代码语言:javascript复制
country_list = ['美国', '意大利', '中国', '西班牙', '德国', '伊朗', '法国', '英国', '瑞士','比利时']
need_data = alltime_data[alltime_data['name'].isin(country_list)]

接下来使用datetime模块生成时间数据,构造时间列表:

代码语言:javascript复制
from datetime import datetime,timedelta
time_list = [(datetime(2020, 3, 1)   timedelta(i)).strftime('%Y-%m-%d') for i in range(31)]

载入Matplotlib库,并设置正常显示中文字体:

代码语言:javascript复制
import matplotlib.pyplot as plt
%matplotlib inline

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['figure.dpi'] = 100

为每个国家设置一种颜色:

代码语言:javascript复制
color_list = ['brown','peru','orange','blue','green',
              'red','yellow','teal','pink','orchid']
country_color = pd.DataFrame()
country_color['country'] = country_list
country_color['color'] = color_list

定义绘图函数:

代码语言:javascript复制
import matplotlib.ticker as ticker

def barh_draw(day):
    
    # 提取每一天的数据
    draw_data = need_data[need_data['date']==day][['name','total_confirm']].sort_values(by='total_confirm',ascending=True)
    
    # 清空当前的绘图
    ax.clear()
    
    # 绘制条形图
    ax.barh(draw_data['name'],draw_data['total_confirm'], color=[country_color[country_color['country']==i]['color'].values[0] for i in draw_data['name']])
    
    # 数值标签的间距
    dx = draw_data['total_confirm'].max()/200
    
    # 添加数值标签
    for j, (name, value) in enumerate(zip(draw_data['name'], draw_data['total_confirm'])):
        
        ax.text(value dx, j, f'{value:,.0f}', size=10, ha='left', va='center')
        
    # 添加日期标签
    ax.text(draw_data['total_confirm'].max()*0.75, 0.4, day, color='#777777',size=40, ha='left')
    
    # 设置刻度标签的格式
    ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
    
    # 设置刻度的位置
    ax.xaxis.set_ticks_position('top')

    # 设置刻度标签的颜色和大小
    ax.tick_params(axis='x',colors='#777777', labelsize=15)
    
    # 添加网格线
    ax.grid(which='major',axis='x',linestyle='-')
    
    # 添加图标题
    ax.text(0, 11, '3月世界各国家累计确诊人数动态条形图',size=20, ha='left')
    
    # 去除图边框
    plt.box(False)
    
    # 关闭绘图框
    plt.close()
代码语言:javascript复制
# 动态绘图
fig, ax = plt.subplots(figsize=(12, 8))

import matplotlib.animation as animation
from IPython.display import HTML

animator = animation.FuncAnimation(fig, barh_draw, frames=time_list, interval=200)
HTML(animator.to_jshtml())

从动态条形图中可以看到,3月初,中国的累计确诊人数排在第一位,由于疫情发生较早且防控措施到位,每日新增人数逐渐减少,疫情基本结束,其它国家的确诊人数还处在萌芽阶段;3月初至3月中旬,意大利、伊朗、西班牙三个国家累计确诊人数突然快速增长,其它几个国家的累计确诊人数也在以较快的速度增长;3月中旬到3月下旬,美国的累计确诊人数飞速增长,迅速超越几个欧洲国家,最终超越中国来到第一位,成为世界上累计确诊人数最多的国家,意大利和西班牙继续快速增长,最终超越中国来到第二位和第三位。

5、总结

本案例使用基于网易实时疫情播报平台爬取的数据,进行新冠肺炎疫情数据的可视化分析。利用pyecharts和Matplotlib绘制了世界地图、玫瑰图、折线图和动态条形图,从现存确诊人数、累计死亡人数、每日新增确诊人数和累计确诊人数四个角度分析全球和部分国家当前的疫情情况。通过本案例,大家可以举一反三,绘制更多的可视化图形,从更多的角度对疫情数据进行分析,希望大家学有所成!

0 人点赞