新冠疫情数据可视化分析

1 数据集说明

这是一份来自 Johns Hopkins University 在github 开源的全球新冠肺炎 COVID-19 数据集,每日时间序列汇总,包括确诊、死亡和治愈。所有数据来自每日病例报告。数据持续更新至2023年3月。

2 数据清洗

In [1]:

import pandas as pd 
confirmed_data = pd.read_csv('time_series_covid19_confirmed_global.csv')
deaths_data = pd.read_csv('time_series_covid19_deaths_global.csv')
recovered_data = pd.read_csv('time_series_covid19_recovered_global.csv')

In [2]:

# 美国的名称格式化:将所有值为'US'的项替换为'United States'
confirmed_data['Country/Region']=confirmed_data['Country/Region'].apply(lambda x: 'United States' if x == 'US' else x)
deaths_data['Country/Region']=deaths_data['Country/Region'].apply(lambda x: 'United States' if x == 'US' else x)
recovered_data['Country/Region']=recovered_data['Country/Region'].apply(lambda x: 'United States' if x == 'US' else x)

# 将台湾的数据归到中国
idx1 = confirmed_data[confirmed_data['Country/Region'] == 'Taiwan*'].index[0]
confirmed_data.loc[idx1, 'Province/State'] = 'Taiwan'
confirmed_data.loc[idx1, 'Country/Region'] = 'China'

idx2 = deaths_data[deaths_data['Country/Region'] == 'Taiwan*'].index[0]
deaths_data.loc[idx2, 'Province/State'] = 'Taiwan'
deaths_data.loc[idx2, 'Country/Region'] = 'China'

idx3 = recovered_data[recovered_data['Country/Region'] == 'Taiwan*'].index[0]
recovered_data.loc[idx3, 'Province/State'] = 'Taiwan'
recovered_data.loc[idx3, 'Country/Region'] = 'China'

In [4]:

# 增加 Country/Region 和 Province/State 的中文冗余列 Country/Region_zh 、Province/State_zh
country_map = {
    'Singapore Rep.': '新加坡', 'Dominican Rep.': '多米尼加', 'Palestine': '巴勒斯坦', 'Bahamas': '巴哈马', 'Timor-Leste': '东帝汶',
    'Afghanistan': '阿富汗', 'Guinea-Bissau': '几内亚比绍', "Côte d'Ivoire": '科特迪瓦', 'Siachen Glacier': '锡亚琴冰川',
    "Br. Indian Ocean Ter.": '英属印度洋领土', 'Angola': '安哥拉', 'Albania': '阿尔巴尼亚', 'United Arab Emirates': '阿联酋',
    'Argentina': '阿根廷', 'Armenia': '亚美尼亚', 'French Southern and Antarctic Lands': '法属南半球和南极领地', 'Australia': '澳大利亚',
    'Austria': '奥地利', 'Azerbaijan': '阿塞拜疆', 'Burundi': '布隆迪', 'Belgium': '比利时', 'Benin': '贝宁', 'Burkina Faso': '布基纳法索',
    'Bangladesh': '孟加拉国', 'Bulgaria': '保加利亚', 'The Bahamas': '巴哈马', 'Bosnia and Herz.': '波斯尼亚和黑塞哥维那', 'Belarus': '白俄罗斯',
    'Belize': '伯利兹', 'Bermuda': '百慕大', 'Bolivia': '玻利维亚', 'Brazil': '巴西', 'Brunei': '文莱', 'Bhutan': '不丹',
    'Botswana': '博茨瓦纳', 'Central African Rep.': '中非', 'Canada': '加拿大', 'Switzerland': '瑞士', 'Chile': '智利',
    'China': '中国', 'Ivory Coast': '象牙海岸', 'Cameroon': '喀麦隆', 'Dem. Rep. Congo': '刚果民主共和国', 'Congo': '刚果',
    'Colombia': '哥伦比亚', 'Costa Rica': '哥斯达黎加', 'Cuba': '古巴', 'N. Cyprus': '北塞浦路斯', 'Cyprus': '塞浦路斯', 'Czech Rep.': '捷克',
    'Germany': '德国', 'Djibouti': '吉布提', 'Denmark': '丹麦', 'Algeria': '阿尔及利亚', 'Ecuador': '厄瓜多尔', 'Egypt': '埃及',
    'Eritrea': '厄立特里亚', 'Spain': '西班牙', 'Estonia': '爱沙尼亚', 'Ethiopia': '埃塞俄比亚', 'Finland': '芬兰', 'Fiji': '斐',
    'Falkland Islands': '福克兰群岛', 'France': '法国', 'Gabon': '加蓬', 'United Kingdom': '英国', 'Georgia': '格鲁吉亚',
    'Ghana': '加纳', 'Guinea': '几内亚', 'Gambia': '冈比亚', 'Guinea Bissau': '几内亚比绍', 'Eq. Guinea': '赤道几内亚', 'Greece': '希腊',
    'Greenland': '格陵兰', 'Guatemala': '危地马拉', 'French Guiana': '法属圭亚那', 'Guyana': '圭亚那', 'Honduras': '洪都拉斯',
    'Croatia': '克罗地亚', 'Haiti': '海地', 'Hungary': '匈牙利', 'Indonesia': '印度尼西亚', 'India': '印度', 'Ireland': '爱尔兰',
    'Iran': '伊朗', 'Iraq': '伊拉克', 'Iceland': '冰岛', 'Israel': '以色列', 'Italy': '意大利', 'Jamaica': '牙买加', 'Jordan': '约旦',
    'Japan': '日本', 'Kazakhstan': '哈萨克斯坦', 'Kenya': '肯尼亚', 'Kyrgyzstan': '吉尔吉斯斯坦', 'Cambodia': '柬埔寨', 'Korea': '韩国',
    'Kosovo': '科索沃', 'Kuwait': '科威特', 'Lao PDR': '老挝', 'Lebanon': '黎巴嫩', 'Liberia': '利比里亚', 'Libya': '利比亚',
    'Sri Lanka': '斯里兰卡', 'Lesotho': '莱索托', 'Lithuania': '立陶宛', 'Luxembourg': '卢森堡', 'Latvia': '拉脱维亚', 'Morocco': '摩洛哥',
    'Moldova': '摩尔多瓦', 'Madagascar': '马达加斯加', 'Mexico': '墨西哥', 'Macedonia': '马其顿', 'Mali': '马里', 'Myanmar': '缅甸',
    'Montenegro': '黑山', 'Mongolia': '蒙古', 'Mozambique': '莫桑比克', 'Mauritania': '毛里塔尼亚', 'Malawi': '马拉维',
    'Malaysia': '马来西亚', 'Namibia': '纳米比亚', 'New Caledonia': '新喀里多尼亚', 'Niger': '尼日尔', 'Nigeria': '尼日利亚',
    'Nicaragua': '尼加拉瓜', 'Netherlands': '荷兰', 'Norway': '挪威', 'Nepal': '尼泊尔', 'New Zealand': '新西兰', 'Oman': '阿曼',
    'Pakistan': '巴基斯坦', 'Panama': '巴拿马', 'Peru': '秘鲁', 'Philippines': '菲律宾', 'Papua New Guinea': '巴布亚新几内亚',
    'Poland': '波兰', 'Puerto Rico': '波多黎各', 'Dem. Rep. Korea': '朝鲜', 'Portugal': '葡萄牙', 'Paraguay': '巴拉圭',
    'Qatar': '卡塔尔', 'Romania': '罗马尼亚', 'Russia': '俄罗斯', 'Rwanda': '卢旺达', 'W. Sahara': '西撒哈拉', 'Saudi Arabia': '沙特阿拉伯',
    'Sudan': '苏丹', 'S. Sudan': '南苏丹', 'Senegal': '塞内加尔', 'Solomon Is.': '所罗门群岛', 'Sierra Leone': '塞拉利昂',
    'El Salvador': '萨尔瓦多', 'Somaliland': '索马里兰', 'Somalia': '索马里', 'Serbia': '塞尔维亚', 'Suriname': '苏里南',
    'Slovakia': '斯洛伐克', 'Slovenia': '斯洛文尼亚', 'Sweden': '瑞典', 'Swaziland': '斯威士兰', 'Syria': '叙利亚', 'Chad': '乍得',
    'Togo': '多哥', 'Thailand': '泰国', 'Tajikistan': '塔吉克斯坦', 'Turkmenistan': '土库曼斯坦', 'East Timor': '东帝汶',
    'Trinidad and Tobago': '特里尼达和多巴哥', 'Tunisia': '突尼斯', 'Turkey': '土耳其', 'Tanzania': '坦桑尼亚', 'Uganda': '乌干达',
    'Ukraine': '乌克兰', 'Uruguay': '乌拉圭', 'United States': '美国', 'Uzbekistan': '乌兹别克斯坦', 'Venezuela': '委内瑞拉',
    'Vietnam': '越南', 'Vanuatu': '瓦努阿图', 'West Bank': '西岸', 'Yemen': '也门', 'South Africa': '南非', 'Zambia': '赞比亚',
    'Zimbabwe': '津巴布韦', 'Comoros': '科摩罗'
}

province_map = {
    'Anhui': '安徽省', 'Beijing': '北京市', 'Chongqing': '重庆市', 'Fujian': '福建省', 'Gansu': '甘肃省', 'Guangdong': '广东省',
    'Guangxi': '广西壮族自治区', 'Guizhou': '贵州省', 'Hainan': '海南省', 'Hebei': '河北省', 'Heilongjiang': '黑龙江省', 'Henan': '河南省',
    'Hong Kong': '香港特别行政区', 'Hubei': '湖北省', 'Hunan': '湖南省', 'Inner Mongolia': '内蒙古自治区', 'Jiangsu': '江苏省',
    'Jiangxi': '江西省', 'Jilin': '吉林省', 'Liaoning': '辽宁省', 'Macau': '澳门特别行政区', 'Ningxia': '宁夏回族自治区', 'Qinghai': '青海省',
    'Shaanxi': '陕西省', 'Shandong': '山东省', 'Shanghai': '上海市', 'Shanxi': '山西省', 'Sichuan': '四川省', 'Tianjin': '天津市',
    'Tibet': '西藏自治区', 'Xinjiang': '新疆维吾尔自治区', 'Yunnan': '云南省', 'Zhejiang': '浙江省', 'Taiwan': '台湾省','Unknown': '澳门特别行政区'
}


confirmed_data['Country/Region_zh'] = confirmed_data['Country/Region'].apply(lambda x: country_map.get(x, x))
deaths_data['Country/Region_zh'] = deaths_data['Country/Region'].apply(lambda x: country_map.get(x, x))
recovered_data['Country/Region_zh'] = recovered_data['Country/Region'].apply(lambda x: country_map.get(x, x))

confirmed_data['Province/State_zh'] = confirmed_data['Province/State'].apply(lambda x: province_map.get(x, x))
deaths_data['Province/State_zh'] = deaths_data['Province/State'].apply(lambda x: province_map.get(x, x))
recovered_data['Province/State_zh'] = recovered_data['Province/State'].apply(lambda x: province_map.get(x, x))

# 将新增的中文名称列 Province/State_zh 和 Country/Region_zh 放在了列的最前面
confirmed_data = confirmed_data[['Province/State_zh', 'Country/Region_zh'] + confirmed_data.columns[:-2].to_list()]
deaths_data = deaths_data[['Province/State_zh', 'Country/Region_zh'] + deaths_data.columns[:-2].to_list()]
recovered_data = recovered_data[['Province/State_zh', 'Country/Region_zh'] + recovered_data.columns[:-2].to_list()]

3 数据可视化及数据分析

3.1 全球新冠疫情情况

3.1.1 全球疫情现状

In [6]:

import pyecharts

from pyecharts import options as opts
from pyecharts.charts import Map, Timeline, Bar, Line
from pyecharts.components import Table
from pyecharts.options import ComponentTitleOpts

lastdate = '6/30/21'

# 计算累计人数
confirmed_total = confirmed_data[lastdate].sum()
deaths_total = deaths_data[lastdate].sum()
recovered_total = recovered_data[lastdate].sum()

# 计算死亡率、康复率
deaths_rate = deaths_total / confirmed_total
recovered_rate = recovered_total / confirmed_total

In [7]:

table = Table()

headers = ['确诊人数', '死亡人数', '治愈人数', '死亡率', '治愈率']
rows = [
    [confirmed_total, deaths_total, recovered_total, f'{deaths_rate:.2%}', f'{recovered_rate:.2%}']   
]
table.add(headers, rows)

table.set_global_opts(title_opts=ComponentTitleOpts(title=f'({lastdate})全球疫情情况'))
table.render_notebook()

(6/30/21)全球疫情情况

确诊人数死亡人数治愈人数死亡率治愈率
18271272639766791195806202.18%65.45%

In [8]:

confirmed = confirmed_data.groupby('Country/Region').agg({lastdate: 'sum'}).to_dict()[lastdate]
deaths = deaths_data.groupby('Country/Region').agg({lastdate: 'sum'}).to_dict()[lastdate]
recovered = recovered_data.groupby('Country/Region').agg({lastdate: 'sum'}).to_dict()[lastdate]
exists_confirmed = {key: value - deaths[key] - recovered[key]  for key, value in confirmed.items()}

wmap = (
    Map()
    .add("确诊人数", [*confirmed.items()], "world", is_map_symbol_show=False)
    .add("治愈人数", [*recovered.items()], "world", is_map_symbol_show=False)
    .add("死亡人数", [*deaths.items()], "world", is_map_symbol_show=False)
    .add("现有确诊人数", [*exists_confirmed.items()], "world", is_map_symbol_show=False)
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(
        title_opts=opts.TitleOpts(title=f'({lastdate})全球疫情现状'),
        visualmap_opts=opts.VisualMapOpts(max_=1000000),  

    )
)
wmap.render_notebook()

截至2021年6月30日,仅有疫情严格管控的国家、人口稀少的国家、经济欠发达人流量少的国家感染人数较少

3.1.2 全球疫情历史发展情况

In [10]:

tl = Timeline()
tl.add_schema(
        is_auto_play=True,
        is_loop_play=False,
        play_interval=200,
    )
# 从第七列开始的所有列
target = confirmed_data.columns[6:].to_list()

# 切片选择每隔7天的日期
target = target[::7]

for dt in target:    
    confirmed = confirmed_data.groupby('Country/Region').agg({dt: 'sum'}).to_dict()[dt]
    c1 = (
        Map()
        .add("确诊人数", [*confirmed.items()], "world", is_map_symbol_show=False)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(
            title_opts=opts.TitleOpts(title="全球疫情历史发展情况"),
            visualmap_opts=opts.VisualMapOpts(max_=1000000),              
        )
    )
    tl.add(c1, dt)
tl.render_notebook()

2020年,疫情较为严重的国家是美国、俄罗斯、巴西、印度

随后2021年加重的是美洲其他国家、欧洲、中东、南非

2021年下半年,除中国外的亚洲国家基本出现了大范围传播

2022年春节期间,中国也出现了疫情蔓延的现象

疫情3年期间,受影响最小的是非洲国家

3.1.3 各国确诊人数排行 TOP20

In [13]:

tl = Timeline()
tl.add_schema(
#         is_auto_play=True,
        is_loop_play=False,
        play_interval=50,
    )

for dt in confirmed_data.columns[6:]:
    confirmed = confirmed_data.groupby('Country/Region_zh').agg({dt: 'sum'}).sort_values(by=dt, ascending=False)[:20].sort_values(by=dt).to_dict()[dt]
    bar = (
        Bar()
        .add_xaxis([*confirmed.keys()])
        .add_yaxis("确诊人数", [*confirmed.values()], label_opts=opts.LabelOpts(position="right"))
        .reversal_axis()
        .set_global_opts(
            title_opts=opts.TitleOpts("各国确诊人数排行 TOP20")
        )
    )
    tl.add(bar, dt)
tl.render_notebook()

早期确诊人数最多的是中国,2020.3以后,疫情重灾区转向欧洲、美洲以及印度

  • 原因是中国武汉最先出现疫情,随后采取有效的防疫措施,控制了确诊人数
  • 除中国以外的大多数国家仅采取了宽松的防疫政策,或是未进行管控,导致疫情在人口密集、经济发达的地区飞速传播

3.1.4 全球疫情趋势

全球“新增确诊人数”呈周期性波动(由于上传大小受限,此处仅展示效果图)

  1. 2020.12:入冬气温下降和圣诞节、新年假期导致人口流动增加、抵抗力下降
  2. 2021.12-2022.3:除去与2020.12相同的原因以外,重要原因是病毒率先发生了变异,成为高传染性的奥密克戎毒株BA.1、BA.2
  3. 2022.7:奥密克戎毒株再次变异,出现传染性更强的BA.4、BA.5型号

3.2 中国新冠疫情情况

3.2.1 中国疫情现状

In [15]:

from pyecharts import options as opts
from pyecharts.charts import Map, Timeline, Bar, Line
from pyecharts.components import Table
from pyecharts.options import ComponentTitleOpts

lastdate = '6/30/21'
confirmed_data_china = confirmed_data[confirmed_data['Country/Region'] == 'China']
deaths_data_china = deaths_data[deaths_data['Country/Region'] == 'China']
recovered_data_china = recovered_data[recovered_data['Country/Region'] == 'China']

confirmed_total_china = confirmed_data_china[lastdate].sum()
deaths_total_china = deaths_data_china[lastdate].sum()
recovered_total_china = recovered_data_china[lastdate].sum()
exists_confirmed_china = confirmed_total_china - deaths_total_china - recovered_total_china

deaths_rate_china = deaths_total_china / confirmed_total_china
recovered_rate_china = recovered_total_china / confirmed_total_china

table = Table()

headers = ['确诊人数', '死亡人数', '治愈人数', '死亡率', '治愈率', '现有确诊人数']
rows = [
    [confirmed_total_china, deaths_total_china, recovered_total_china, f'{deaths_rate_china:.2%}', f'{recovered_rate_china:.2%}', exists_confirmed_china],    
]
table.add(headers, rows)
table.set_global_opts(
    title_opts=ComponentTitleOpts(title=f'({lastdate})中国疫情情况')
)
table.render_notebook()

(6/30/21)中国疫情情况

确诊人数死亡人数治愈人数死亡率治愈率现有确诊人数
12838156811085954.43%84.59%14105

2021年6月,全国疫情处于平稳期,传播趋势在防疫政策的管控下得到了有效遏制(此处受限文件大小,未展示图片)

3.2.2 中国疫情历史发展情况

In [17]:

tl = Timeline()
tl.add_schema(
#         is_auto_play=True,
        is_loop_play=False,
        play_interval=200,
    )
target = confirmed_data_china.columns[6:].to_list()
target.reverse()
target = target[::7]
target.reverse()
for dt in target:    
    confirmed = confirmed_data_china.groupby('Province/State_zh').agg({dt: 'sum'}).to_dict()[dt]
    c = (
        Map()
        .add("确诊人数", [*confirmed.items()], "china", is_map_symbol_show=False)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=True))
        .set_global_opts(
            title_opts=opts.TitleOpts(title='中国疫情历史发展情况'),
            visualmap_opts=opts.VisualMapOpts(max_=2000),            
        )
    )
    tl.add(c, dt)
tl.render_notebook()

中国疫情起源于湖北省,可以观察到:

  1. 疫情从湖北省率先传播到了周边省份,具有空间溢出效应
  2. 防控松懈、管理难度大、人口众多的省份确诊人数上升迅速
  3. 经济欠发达地区、山地多的地区确诊人数上升缓慢
  4. 截至2023年3月,全国各地均发现确诊病例

3.2.3 各省确诊人数排行 TOP20

(由于上传大小受限,此处仅展示效果图)

趋势:2022.3以前,湖北省累计确诊最多;2022.3以后,港澳台累计确诊迅速登顶

原因:2022.3以前,新冠病毒传染性不够强;2022.3以后,病毒变异为传染性极强的奥密克戎,未严格实行防疫政策的地区确诊人数飙升

3.2.4 中国疫情趋势

In [19]:

targets = confirmed_data_china.columns[6:].to_list()
new_confirmed_list = []
new_deaths_list = []
new_recovered_list = []
exists_confirmed_list = []
for idx, today in enumerate(targets[1:], 1):
    yesterday = targets[idx-1]
    new_confirmed = confirmed_data_china[today].sum() - confirmed_data_china[yesterday].sum()
    new_deaths = deaths_data_china[today].sum() - deaths_data_china[yesterday].sum()
    new_recovered = recovered_data_china[today].sum() - recovered_data_china[yesterday].sum()
    exists_confirmed = confirmed_data_china[today].sum() - deaths_data_china[today].sum() - recovered_data_china[today].sum()
    new_confirmed_list.append(int(new_confirmed))
    new_deaths_list.append(int(new_deaths))
    new_recovered_list.append(int(new_recovered))
    exists_confirmed_list.append(int(exists_confirmed))
c = (
    Line()
    .add_xaxis(targets[1:])
    .add_yaxis('新增确诊人数', new_confirmed_list, label_opts=opts.LabelOpts(is_show=False), is_symbol_show=False)
    .add_yaxis('新增治愈人数', new_recovered_list, label_opts=opts.LabelOpts(is_show=False), is_symbol_show=False)
    .add_yaxis('新增死亡人数', new_deaths_list, label_opts=opts.LabelOpts(is_show=False), is_symbol_show=False)
    .add_yaxis('现有确诊人数', exists_confirmed_list, label_opts=opts.LabelOpts(is_show=False), is_symbol_show=False)
    .set_global_opts(title_opts=opts.TitleOpts(title="中国疫情趋势"))
)
c.render_notebook()

“新增确诊人数”出现3个高峰

  • 2022.2:原因是全世界抗疫不积极,且变异病毒奥密克戎出现,传播性更强;以及春节返乡返岗,隐患人群大面积聚集导致快速传播
  • 2022.5:原因是距离去年12月份开始的大传播已经有6个月,人体内的病毒抗体下降,对新冠的免疫水平降低,更容易感染
  • 2022.12:原因是中国3年疫情2022年12月13日开始全面放开;以及冬季寒潮来临,人群免疫力下降

4 新冠疫情数据分析结论

4.1 疫情防控核心指标为“新增确诊人数”

原因如下:

1. 新增确诊人数能够快速反映地区感染风险趋势,易于观测
2. 帮助政府快速向潜在高风险地区分配防疫资源
3. 有利于居民及时应对,预防未来可能的病毒感染
4. 新增确诊人数计算较简单,能够适应疫情快速蔓延的局势
5. 在本分析中,新增确诊人数属于先导指标,相比于治愈人数、死亡人数等,更能及时反映疫情变化

4.2 新冠疫情传播具有一定规律

1. 发达地区传播早
2. 人口稠密地区传播快
3. 寒冷地区易感染
4. 节日开放新增多
5. 高风险地区对周边具有辐射效应

  • 结论基本符合本次新冠疫情的传播特点,能够为日后类似传染病传播提供防控参考

4.3 中国疫情防控政策效果显著

1. 截止至2021年6月30日,全球与中国治愈率总体较高,均在65%以上;全球比中国死亡率低,总体在3%以下
2. 中国治愈率高于全球平均水平,达84.59%;死亡率略高于全球平均水平,达4.43%

  • 原因可能是:2021年6月30日前后,中国新增确诊人数增长缓慢,而全球新增确诊人数增长较快,导致中国累计确诊基数小,进而导致死亡率偏高
  • 这侧面说明了中国疫情防控政策的有效性,且不能从单一指标评判防疫成果
  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴躁的秋秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值