欢迎光临散文网 会员登陆 & 注册

用Python进行新型冠状病毒(COVID-19/2019-nCoV)疫情分析(上)

2020-08-04 15:22 作者:祈LHL  | 我要投稿

重要说明

分析文档:完成度:代码质量 3:5:2    

其中分析文档是指你数据分析的过程中,对各问题分析的思路、对结果的解释、说明(要求言简意赅,不要为写而写)    

由于数据过多,查看数据尽量使用head()或tail(),以免程序长时间无响应


=======================   


本项目数据来源于丁香园。本项目主要目的是**通过对疫情历史数据的分析研究,以更好的了解疫情与疫情的发展态势,为抗击疫情之决策提供数据支持。**     

关于本章使用的数据集,欢迎点击——>我的视频      在评论区获取。

一. 提出问题


从全国范围,你所在省市,国外疫情等三个方面主要研究以下几个问题:


(一)全国累计确诊/疑似/治愈/死亡情况随时间变化趋势如何?


(二)全国新增确诊/疑似/治愈/死亡情况随时间变化趋势如何?


(三)全国新增境外输入随时间变化趋势如何?


(四)你所在的省市情况如何?


(五)国外疫情态势如何?


(六)结合你的分析结果,对个人和社会在抗击疫情方面有何建议?



 二. 理解数据

原始数据集:AreaInfo.csv,导入相关包及读取数据:

r_hex = '#dc2624'     # red,       RGB = 220,38,36

dt_hex = '#2b4750'    # dark teal, RGB = 43,71,80

tl_hex = '#45a0a2'    # teal,      RGB = 69,160,162

r1_hex = '#e87a59'    # red,       RGB = 232,122,89

tl1_hex = '#7dcaa9'   # teal,      RGB = 125,202,169

g_hex = '#649E7D'     # green,     RGB = 100,158,125

o_hex = '#dc8018'     # orange,    RGB = 220,128,24

tn_hex = '#C89F91'    # tan,       RGB = 200,159,145

g50_hex = '#6c6d6c'   # grey-50,   RGB = 108,109,108

bg_hex = '#4f6268'    # blue grey, RGB = 79,98,104

g25_hex = '#c7cccf'   # grey-25,   RGB = 199,204,207

import numpy as np

import pandas as pd

import matplotlib,re

import matplotlib.pyplot as plt

from matplotlib.pyplot import MultipleLocator



data = pd.read_csv(r'data/AreaInfo.csv')


**查看与统计数据,以对数据有一个大致了解**


data.head()


三. 数据清洗


(一)基本数据处理


数据清洗主要包括:**选取子集,缺失数据处理、数据格式转换、异常值数据处理**等。


国内疫情数据选取(最终选取的数据命名为china)


1. 选取国内疫情数据


2. 对于更新时间(updateTime)列,需将其转换为日期类型并提取出年-月-日,并查看处理结果。(提示:dt.date)


3. 因数据每天按小时更新,一天之内有很多重复数据,请去重并只保留一天之内最新的数据。


> 提示:df.drop_duplicates(subset=['provinceName', 'updateTime'], keep='first', inplace=False)


> 其中df是你选择的国内疫情数据的DataFrame


分析:选取countryName一列中值为中国的行组成CHINA。


CHINA = data.loc[data['countryName'] == '中国']

CHINA.dropna(subset=['cityName'], how='any', inplace=True)

#CHINA


分析:取出含所有中国城市的列表


cities = list(set(CHINA['cityName']))


分析:遍历取出每一个城市的子dataframe,然后用sort对updateTime进行时间排序


for city in cities:

    CHINA.loc[data['cityName'] == city].sort_values(by = 'updateTime')


分析:去除空值所在行


CHINA.dropna(subset=['cityName'],inplace=True)

#CHINA.loc[CHINA['cityName'] == '秦皇岛'].tail(20)

#检查部分数据


 分析:将CHINA中的updateTime列进行格式化处理


CHINA.updateTime = pd.to_datetime(CHINA.updateTime,format="%Y-%m-%d",errors='coerce').dt.date

#CHINA.loc[data['cityName'] == '秦皇岛'].tail(15)

#部分数据检查


CHINA.head()


分析:每日数据的去重只保留第一个数据,因为前面已经对时间进行排序,第一个数据即为当天最新数据   


分析:考虑到合并dataframe需要用到concat,需要创建一个初始china


real = CHINA.loc[data['cityName'] == cities[1]]

real.drop_duplicates(subset='updateTime', keep='first', inplace=True)

china = real


分析:遍历每个城市dataframe进行每日数据的去重,否则会出现相同日期只保留一个城市的数据的情况


for city in cities[2:]:

    real_data = CHINA.loc[data['cityName'] == city]

    real_data.drop_duplicates(subset='updateTime', keep='first', inplace=True)

    china = pd.concat([real_data, china],sort=False)

查看数据信息,是否有缺失数据/数据类型是否正确。


提示:若不会处理缺失值,可以将其舍弃


分析:有的城市不是每日都上报的,如果某日只统计上报的那些城市,那些存在患者却不上报的城市就会被忽略,数据就失真了,需要补全所有城市每日的数据,即便不上报的城市也要每日记录数据统计,所以要进行插值处理补全部分数据,处理方法详见数据透视与分析

china.info()



    <class 'pandas.core.frame.DataFrame'>

    Int64Index: 32812 entries, 96106 to 208267

    Data columns (total 19 columns):

     #   Column                   Non-Null Count  Dtype  

    ---  ------                   --------------  -----  

     0   continentName            32812 non-null  object 

     1   continentEnglishName     32812 non-null  object 

     2   countryName              32812 non-null  object 

     3   countryEnglishName       32812 non-null  object 

     4   provinceName             32812 non-null  object 

     5   provinceEnglishName      32812 non-null  object 

     6   province_zipCode         32812 non-null  int64  

     7   province_confirmedCount  32812 non-null  int64  

     8   province_suspectedCount  32812 non-null  float64

     9   province_curedCount      32812 non-null  int64  

     10  province_deadCount       32812 non-null  int64  

     11  updateTime               32812 non-null  object 

     12  cityName                 32812 non-null  object 

     13  cityEnglishName          31968 non-null  object 

     14  city_zipCode             32502 non-null  float64

     15  city_confirmedCount      32812 non-null  float64

     16  city_suspectedCount      32812 non-null  float64

     17  city_curedCount          32812 non-null  float64

     18  city_deadCount           32812 non-null  float64

    dtypes: float64(6), int64(4), object(9)

    memory usage: 5.0+ MB

    


china.head()


你所在省市疫情数据选取(最终选取的数据命名为myhome)


此步也可在后面用到的再做


myhome = china.loc[data['provinceName'] == '广东省']

myhome.head()


国外疫情数据选取(最终选取的数据命名为world)


此步也可在后面用到的再做



world = data.loc[data['countryName'] != '中国']

world.head()


数据透视与分析


分析:对china进行插值处理补全部分数据


分析:先创建省份列表和日期列表,并初始化一个draft


province = list(set(china['provinceName']))#每个省份

#p_city = list(set(china[china['provinceName'] == province[0]]['cityName']))#每个省份的城市

date_0 = []

for dt in china.loc[china['provinceName'] ==  province[0]]['updateTime']:

    date_0.append(str(dt))

date_0 = list(set(date_0))

date_0.sort()

start = china.loc[china['provinceName'] ==  province[0]]['updateTime'].min()

end = china.loc[china['provinceName'] ==  province[0]]['updateTime'].max()

dates = pd.date_range(start=str(start), end=str(end))

aid_frame = pd.DataFrame({'updateTime': dates,'provinceName':[province[0]]*len(dates)})

aid_frame.updateTime = pd.to_datetime(aid_frame.updateTime,format="%Y-%m-%d",errors='coerce').dt.date

#draft = pd.merge(china.loc[china['provinceName'] ==  province[1]], aid_frame, on='updateTime', how='outer').sort_values('updateTime')

draft = pd.concat([china.loc[china['provinceName'] ==  province[0]], aid_frame], join='outer').sort_values('updateTime')

draft.province_confirmedCount.fillna(method="ffill",inplace=True)

draft.province_suspectedCount.fillna(method="ffill", inplace=True)

draft.province_curedCount.fillna(method="ffill", inplace=True)

draft.province_deadCount.fillna(method="ffill", inplace=True)


分析:补全部分时间,取前日的数据进行插值,因为有的省份从4月末开始陆续就不再有新增病患,不再上报,所以这些省份的数据只能补全到4月末,往后的数据逐渐失去真实性


分析:同时进行日期格式化


for p in range(1,len(province)):

    date_d = []

    for dt in china.loc[china['provinceName'] ==  province[p]]['updateTime']:

        date_d.append(dt)

    date_d = list(set(date_d))

    date_d.sort()

    start = china.loc[china['provinceName'] ==  province[p]]['updateTime'].min()

    end = china.loc[china['provinceName'] ==  province[p]]['updateTime'].max()

    dates = pd.date_range(start=start, end=end)

    aid_frame = pd.DataFrame({'updateTime': dates,'provinceName':[province[p]]*len(dates)})

    aid_frame.updateTime = pd.to_datetime(aid_frame.updateTime,format="%Y-%m-%d",errors='coerce').dt.date

    X = china.loc[china['provinceName'] ==  province[p]]

    X.reset_index(drop= True)

    Y = aid_frame

    Y.reset_index(drop= True)

    draft_d = pd.concat([X,Y], join='outer').sort_values('updateTime')

    draft = pd.concat([draft,draft_d])

    draft.province_confirmedCount.fillna(method="ffill",inplace=True)

    draft.province_suspectedCount.fillna(method="ffill", inplace=True)

    draft.province_curedCount.fillna(method="ffill", inplace=True)

    draft.province_deadCount.fillna(method="ffill", inplace=True)

    #draft['updateTime'] = draft['updateTime'].strftime('%Y-%m-%d')

    #draft['updateTime'] = pd.to_datetime(draft['updateTime'],format="%Y-%m-%d",errors='coerce').dt.date


china = draft


china.head()

四. 数据分析及可视化

在进行数据分析及可视化时,依据每个问题选取所需变量并新建DataFrame再进行分析和可视化展示,这样数据不易乱且条理更清晰。

基础分析

基础分析,只允许使用numpy、pandas和matplotlib库

可以在一张图上多个坐标系展示也可以在多张图上展示

请根据分析目的选择图形的类型(折线图、饼图、直方图和散点图等等),实在没有主意可以到百度疫情地图或其他疫情分析的站点激发激发灵感。

(一)全国累计确诊/疑似/治愈/死亡情况随时间变化趋势如何?

分析:要获得全国累计情况随时间变化趋势,首先需要整合每日全国累计确诊情况做成date_confirmed

分析:要整合每日全国累计确诊情况,首先得提取每个省份每日当天最新累计确诊人数,省份数据求和后形成dataframe,for循环拼接到date_confirmed中


date = list(set(china['updateTime']))

date.sort()


china = china.set_index('provinceName')

china = china.reset_index()


分析:循环遍历省份和日期获得每个省份每日累计确诊,因为需要拼接,先初始化一个date_confirmed



list_p = []

list_d = []

list_e = []

for p in range(0,32):

    try:

        con_0 = china.loc[china['updateTime'] == date[2]].loc[china['provinceName'] ==  province[p]].iloc[[0]].iloc[0] 

        list_p.append(con_0['province_confirmedCount'])#该日每省的累计确诊人数

    except:

        continue

list_d.append(sum(list_p))

list_e.append(str(date[0]))

date_confirmed = pd.DataFrame(list_d,index=list_e)

date_confirmed.index.name="date"

date_confirmed.columns=["China_confirmedCount"]

#date_confirmed

分析:遍历每个省份拼接每日的总确诊人数的dataframe



l = 0

for i in date[3:]:

    list_p = []

    list_d = []

    list_e = []

    l +=1

    for p in range(0,32):

        try:

            con_0 = china.loc[china['updateTime'] == date[l]].loc[china['provinceName'] ==  province[p]].iloc[[0]].iloc[0] 

            list_p.append(con_0['province_confirmedCount'])#该日每省的累计确诊人数

        except:

            continue

    #con_0 = china.loc[china['updateTime'] == date[0]].loc[china['provinceName'] == '河北省'].loc[[0]].iloc[0]

    #list_p.append(con_0['province_confirmedCount'])#该日每省的累计确诊人数

    list_d.append(sum(list_p))

    list_e.append(str(date[l]))

    confirmed = pd.DataFrame(list_d, index=list_e)

    confirmed.index.name="date"

    confirmed.columns=["China_confirmedCount"]

    date_confirmed = pd.concat([date_confirmed,confirmed],sort=False)

#date_confirmed

分析:去除空值和不全的值



date_confirmed.dropna(subset=['China_confirmedCount'],inplace=True)

date_confirmed.tail(20)


输出图

分析:数据从4月末开始到5月末就因为缺失过多省份的数据(部分省份从4月末至今再也没有新增病患)而失真,自2020-06-06起完全失去真实性,所以我删除了2020-06-06往后的数据



date_confirmed = date_confirmed.drop(['2020-06-06','2020-06-07','2020-06-08','2020-06-09','2020-06-10','2020-06-11','2020-06-12','2020-06-13','2020-06-14',

                     '2020-06-15','2020-06-16','2020-06-19','2020-06-18','2020-06-20','2020-06-17','2020-06-21'])

分析:构造拼接函数



def data_frame(self,china,element):

    l = 0

    for i in date[3:]:

        list_p = []

        list_d = []

        list_e = []

        l +=1

        for p in range(0,32):

            try:

                con_0 = china.loc[china['updateTime'] == date[l]].loc[china['provinceName'] ==  province[p]].iloc[[0]].iloc[0] 

                list_p.append(con_0[element])

            except:

                continue

        #con_0 = china.loc[china['updateTime'] == date[0]].loc[china['provinceName'] == '河北省'].loc[[0]].iloc[0]

        #list_p.append(con_0['province_confirmedCount'])

        list_d.append(sum(list_p))

        list_e.append(str(date[l]))

        link = pd.DataFrame(list_d, index=list_e)

        link.index.name="date"

        link.columns=["China"]

        self = pd.concat([self,link],sort=False)

    self.dropna(subset=['China'],inplace=True)

    self = self.drop(['2020-06-06','2020-06-07','2020-06-08','2020-06-09','2020-06-10','2020-06-11','2020-06-12','2020-06-13','2020-06-14',

                  '2020-06-15','2020-06-16','2020-06-19','2020-06-18','2020-06-20','2020-06-17','2020-06-21'])

    return self

分析:初始化各个变量



#累计治愈人数  date_curedCount

list_p = []

list_d = []

list_e = []

for p in range(0,32):

    try:

        con_0 = china.loc[china['updateTime'] == date[2]].loc[china['provinceName'] ==  province[p]].iloc[[0]].iloc[0] 

        list_p.append(con_0['province_curedCount'])

    except:

        continue

list_d.append(sum(list_p))

list_e.append(str(date[0]))

date_cured = pd.DataFrame(list_d, index=list_e)

date_cured.index.name="date"

date_cured.columns=["China"]




#累计死亡人数  date_dead

list_p = []

list_d = []

list_e = []

for p in range(0,32):

    try:

        con_0 = china.loc[china['updateTime'] == date[2]].loc[china['provinceName'] ==  province[p]].iloc[[0]].iloc[0] 

        list_p.append(con_0['province_deadCount'])

    except:

        continue

list_d.append(sum(list_p))

list_e.append(str(date[0]))

date_dead = pd.DataFrame(list_d, index=list_e)

date_dead.index.name="date"

date_dead.columns=["China"]


#累计确诊患者  date_confirmed

plt.rcParams['font.sans-serif'] = ['SimHei'] #更改字体,否则无法显示汉字

fig = plt.figure( figsize=(16,6), dpi=100)

ax = fig.add_subplot(1,1,1)

x = date_confirmed.index

y = date_confirmed.values

ax.plot( x, y, color=dt_hex, linewidth=2, linestyle='-' )

ax.set_title('累计确诊患者',fontdict={

      'color':'black',

      'size':24

})

ax.set_xticks( range(0,len(x),30))

全国累计确诊

#累计治愈患者 date_curedCount

date_cured = data_frame(date_cured,china,'province_curedCount')

fig = plt.figure( figsize=(16,6), dpi=100)

ax = fig.add_subplot(1,1,1)

x = date_cured.index

y = date_cured.values

ax.set_title('累计治愈患者',fontdict={

      'color':'black',

      'size':24

})

ax.plot( x, y, color=dt_hex, linewidth=2, linestyle='-' )

ax.set_xticks( range(0,len(x),30))

全国累计治愈

分析:累计疑似无法通过补全数据得到

#累计死亡患者 date_dead

date_dead = data_frame(date_dead,china,'province_deadCount')

fig = plt.figure( figsize=(16,6), dpi=100)

ax = fig.add_subplot(1,1,1)

x = date_dead.index

y = date_dead.values

ax.plot( x, y, color=dt_hex, linewidth=2, linestyle='-' )

x_major_locator=MultipleLocator(12)

ax=plt.gca()

ax.set_title('累计死亡患者',fontdict={

      'color':'black',

      'size':24

})

ax.xaxis.set_major_locator(x_major_locator)

ax.set_xticks( range(0,len(x),30))

全国累计死亡

分析:疫情自1月初开始爆发,到2月末开始减缓增速,到4月末趋于平缓。治愈人数自2月初开始大幅增加,到3月末趋于平缓,死亡人数自1月末开始增加,到2月末趋于平缓,到4月末因为统计因素死亡人数飙升后趋于平缓。
分析总结:确诊人数数据和治愈数据从4月末开始到5月末就因为缺失过多省份的数据(部分省份至今再也没有新增病患)导致失真,其他数据尽量通过补全,越靠近尾部数据越失真。死亡数据补全较为成功,几乎没有错漏。


用Python进行新型冠状病毒(COVID-19/2019-nCoV)疫情分析(上)的评论 (共 条)

分享到微博请遵守国家法律