Advertisement

32 | 全球新冠肺炎确诊病例趋势分析

阅读量:

👉👉👉 《玩转Python数据分析专栏》👈👈👈

订阅本专栏的可以下载对应的代码和数据集

任务背景

过去的一年多时间里,对人类影响最深的事件莫过于全球新冠肺炎的大流行。这一流行病不仅给患者带来了痛苦,也对医疗体系造成了巨大压力。医疗资源紧张是导致许多患者陷入危险的根源。若能基于现有确诊数据预测未来可能的病例数量,政府和医疗机构便能提前规划和准备医疗资源,从而显著改善确诊患者的医疗条件。

因此,新冠肺炎的传播趋势研究也引起了广泛关注。数据分析竞赛平台kaggle则持续提供多套相关数据集,供数据分析爱好者进行研究。

今天,我们利用其中一份数据集致力于预测不同国家的疫情发展动态。

train.csv 的格式如下:

Id: 这是一个唯一的标识符,可能是用来区分每一条数据记录的编号。

Province_State: 该列记录了疫情数据对应的省份/州的名称。在一些国家,疫情数据通常会根据不同的省份或州分别统计,该列可能用于标识具体的空间区域。

Country_Region: 该字段编码了疫情数据对应的国家或地区的名称,例如,'Afghanistan'代表阿富汗。

Date: 该列存储了数据的日期,采用年/月/日的格式存储。在本例中,起始时间为2020年1月22日。

ConfirmedCases: 该列表示每个日期对应的累计确诊病例数量。根据日期和地区的不同,该数字可能有所变化。

Fatalities: 该列记录了每天的累计死亡人数。随着日期的发展,该数字可能会增加。

该表格详细记录了自2020年1月22日起,在全球不同国家和地区范围内,每天的新冠肺炎确诊病例和死亡病例数据。

test.csv 的格式没有ConfirmedCases和Fatalities、

首先我们导入必要的工具包:

复制代码
    import pandas as pd 
    import matplotlib.pyplot as plt
    import numpy as np
    import seaborn as sns 
    import numpy as np
    import random
    from plotly import tools
    import plotly.express as px
    from plotly.offline import init_notebook_mode, iplot, plot 
    import plotly.figure_factory as ff
    import plotly.graph_objs as go 
    
    
    
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI助手

然后我们导入两个数据文件,分别查看:

复制代码
    df_train = pd.read_csv("train.csv")
    
    df_test = pd.read_csv("test.csv")
    
    # 首先查看 train 文件中的内容
    
    df_train
    
    
      
      
      
      
      
      
      
    
    AI助手

生成数据概览中可以看出,该训练数据集共计 3500 余条记录,时间范围从 2020 年 1 月 22 日至 2020 年 5 月 15 日,系统记录了不同国家每天的确诊病例和死亡病例数据。经观察发现,省份字段存在大量缺失值,建议在数据清洗阶段进行补充和完善。

然后看一下 test 数据:

可以看出,test 包含的数据相当多,字段与 train 集类似,不包含确诊病例数和死亡病例数。时间范围为4月至5月,值得注意的是时间和 train 数据集存在部分重叠。

基于 test 数据集的分布情况,本次分析的核心目标已基本明确:通过 train 数据集训练出模型,随后在 test 数据集中对不同国家不同日期的新冠肺炎确诊病例数和死亡病例数进行预测。

接下来,就进入了清洗数据的环节

复制代码
    df_train = df_train.fillna("")
    
    
    
      
      
    
    AI助手

接下来,进入数据分析与可视化的环节。

我们首先从国家维度切入,考察不同国家的历史确诊比例。由于该数据表中的数据是随时间变化的历史确诊比例数,直接对国家维度进行聚合会多计大量重复内容。

基于上面的分析,分国家确诊病例数我们可以这样处理:

首先按国家、省份、和日期维度聚合,并求和;

之后按国家和省份维度聚合,但聚合方式为取最大值;

最后按照国家维度聚合求和,并排序。

复制代码
    df_countries = df_train.groupby(["Country_Region","Province_State","Date"])["ConfirmedCases"].sum()
    df_countries = df_countries.groupby(["Country_Region", "Province_State"]).max()
    df_countries = df_countries.groupby(["Country_Region"]).sum().sort_values(ascending=False)
    # 取前 20 条画图
    df_countries = df_countries.head(20)
    
    
      
      
      
      
      
    
    AI助手

执行之后,下一步我们使用 plotly 将图表画出来:

复制代码
    fig = px.bar(df_countries, x=df_countries.index, y='ConfirmedCases', labels={'x':'Country'},
             color="ConfirmedCases", color_continuous_scale=px.colors.sequential.Bluered)
    fig.update_layout(title_text='国家历史最高确诊数')
    fig.show()
    
    
      
      
      
      
    
    AI助手

数据显示,美国的确诊病例数远高于其他国家。通过点击查看,我们可以了解不包括美国在内的其他国家情况。

即使排除了美国,剩余国家之间的差异仍然显著。从这些图表中可以看出,国家这一特征应当被视为预测确诊病例数的关键因素之一。

接下来我们以美国为例,来分析一下确诊病例随着时间的变化趋势。

复制代码
    # 首先过滤出所有美国的记录,并取省份、日期和确诊数,死亡数等字段
    df_usa_records = df_train.loc[df_train["Country_Region"]=="US", ["Province_State","Date", "ConfirmedCases", "Fatalities"]]
    # 将上述记录按日期维度聚合,同时这会抛弃省份维度
    df_usa_records = df_usa_records.groupby("Date").sum()
    # 重置索引(自动添加序号索引),否则会用 date 作为索引,不方便画图
    df_usa_records = df_usa_records.reset_index()
    # 查看
    df_usa_records
    
    
      
      
      
      
      
      
      
      
    
    AI助手

接下来,我们继续使用 plotly 将其画出来:

复制代码
    fig = px.bar(df_usa_records,x='Date', y='ConfirmedCases', color="ConfirmedCases", color_continuous_scale=px.colors.sequential.Magma)
    fig.update_layout(title_text='美国随时间确诊病例数')
    fig.show()
    
    
      
      
      
    
    AI助手

该数据表的时间维度跨越了2020年2月至5月。在此时段,全球多数国家已基本实现了有效控制,唯有中国仍处于特殊时期。观察图表可知,自3月中旬以来,的确诊病例已降至零。但自3月中旬起,确诊病例数持续攀升,呈现出显著上升趋势。由此可见,时间维度同样扮演着关键角色,是数据分析的重要考量因素。

接下来我们看一下美国的死亡病例数:

复制代码
    fig = px.bar(df_usa_records,x='Date', y='Fatalities', color="Fatalities", color_continuous_scale=px.colors.sequential.Magma)
    fig.update_layout(title_text='美国随时间死亡病例数')
    fig.show()
    
    
      
      
      
    
    AI助手

我们再随机抽样另一个国家的数据情况,比如巴西。代码如下:

复制代码
    df_brz_records = df_train.loc[df_train["Country_Region"]=="Brazil", ["Province_State","Date", "ConfirmedCases", "Fatalities"]]
    df_brz_records = df_brz_records.groupby("Date").sum()
    df_brz_records = df_brz_records.reset_index()
    fig = px.bar(df_brz_records,x='Date', y='ConfirmedCases', color="ConfirmedCases", color_continuous_scale=px.colors.sequential.Magma)
    fig.update_layout(title_text='巴西随时间确诊病例数')
    fig.show()
    
    
      
      
      
      
      
      
    
    AI助手

我们再随机抽样另一个国家的数据情况,比如巴西。代码如下:

复制代码
    fig = px.bar(df_brz_records,x='Date', y='Fatalities', color="Fatalities", color_continuous_scale=px.colors.sequential.Magma)
    fig.update_layout(title_text='巴西随时间死亡病例数')
    fig.show()
    
    
      
      
      
    
    AI助手

根据上图观察到,巴西的疫情数据与美国具有相似性,且持续增长。值得注意的是,自4月下旬以来,巴西的增长速度明显快于美国。从这一现象中可以看出,尽管各国的确诊病例总量存在差异,但疫情发展轨迹也呈现出显著的分化。这进一步表明,国家维度是一个重要的研究维度。

(1)处理日期数据

处理日期数据的方法主要是通过将日期转换为三个数字:年、月、日,并分别新建字段。具体处理步骤及代码实现如下:

复制代码
    # 传入日期,将其用 - 分割,并返回第一部分,即年
    def get_year(date_str):
    comps = date_str.split("-")
    return int(comps[0])
    # 传入日期,将其用 - 分割,并返回第二部分,即月
    def get_month(date_str):
    comps = date_str.split("-")
    return int(comps[1])
    # 传入日期,将其用 - 分割,并返回第三部分,即日
    def get_day(date_str):
    comps = date_str.split("-")
    return int(comps[2])
    # 分别对 Date 字段 apply 上述三个函数,并用结果新建对应的 列
    df_train["Year"] = df_train.Date.apply(get_year)
    df_train["Month"] = df_train.Date.apply(get_month)
    df_train["Day"] = df_train.Date.apply(get_day)
    # 查看
    df_train
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    AI助手

可以看到,我们已经将日期分别拆成了年、月、日三个新的字段。

(2)处理国家的特征

在数据筛选环节,省份处理存在较多缺失数据。然而,约1/3的数据仍然具有有效的值。因此,我们不能仅凭此直接舍弃该字段。然而,将其直接作为模型特征可能会影响分析结果。

所以,我们将省份信息直接整合到国家维度中,并将国家与省份信息组合为一个特征维度。这样既能充分运用省份信息,又能有效减少因过多缺失值对模型的影响。代码如下:

复制代码
    df_train["Country_Region"] = df_train["Country_Region"] + df_train["Province_State"]
    df_train["Country_Region"].value_counts()``
    
    from sklearn.preprocessing import LabelEncoder
    encoder = LabelEncoder()
    df_train["Country_Region"] = encoder.fit_transform(df_train["Country_Region"])
    df_train
    
    
      
      
      
      
      
      
      
    
    AI助手

``(3)抽取训练特征和目标特征

接下来,我们从原始数据表中剔除不必要的因素,构建用于训练的特征集合,并分离出ConfirmedCases字段作为预测目标。代码如下:

复制代码
    df_train_final = df_train[["Country_Region", "Year", "Month", "Day"]]
    labels = df_train.ConfirmedCases
    
    
      
      
    
    AI助手

从我们表中可观察到,编码将国家表示为序号。这些数值虽然以数字形式呈现,但其大小并无实际意义。例如,1代表阿富汗,2代表美国,3代表巴拿马。值得注意的是,阿富汗和巴拿马的数值较小,而美国的数值较大。这反映了非线性关系的特征,即不能依据数值大小来判断其重要性。然而,回顾之前的分析,国家这一变量对于确诊病例数的变化具有关键影响。

这类非线性特征往往依赖于非线性模型的采用。采用xgboost作为当前最常用的技术,以便建立模型。

复制代码
    # 导入 xgboost
    from xgboost import XGBRegressor
    # 创建 xgboost,并配置参数
    xgb = XGBRegressor(n_estimators = 2500 , random_state = 0 , max_depth = 27)
    # 对我们刚才准备的特征进行训练
    xgb.fit(df_train_final, labels)
    
    
      
      
      
      
      
      
    
    AI助手

在模型训练完成之后,我们有必要对 test 数据集进行预测。首先,我们需要对 test 数据集执行与 train 数据集相同的处理步骤,其中包括拆分日期和合并国家及省份等信息。为了确保预测特征与训练特征保持一致,以便利用之前训练好的模型进行预测。

复制代码
    df_test = df_test.fillna("")
    df_test["Year"] = df_test.Date.apply(get_year)
    df_test["Month"] = df_test.Date.apply(get_month)
    df_test["Day"] = df_test.Date.apply(get_day)
    df_test["Country_Region"] = df_test["Country_Region"] + df_test["Province_State"]
    df_test_final = df_test[["Country_Region", "Year", "Month", "Day"]]
    df_test_final["Country_Region"] = encoder.fit_transform(df_test_final["Country_Region"])
    df_test["predict_confirm"] = xgb.predict(df_test_final)
    df_test
    
    
      
      
      
      
      
      
      
      
      
    
    AI助手

👉👉👉 《玩转Python数据分析专栏》👈👈👈

订阅本专栏的可以下载对应的代码和数据集

全部评论 (0)

还没有任何评论哟~