新型冠状病毒数据可视化分析

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了新型冠状病毒数据可视化分析相关的知识,希望对你有一定的参考价值。

导言

如何成为Python数据分析师?

荀子曰:不积跬步,无以至千里;不积小流,无以成江海。
要成为合格的数据分析师需要多加练习,再牛的数据分析师不练习也会逐渐落伍

孔子曰:工欲善其事,必先利其器。
数据分析工具、可视化工具可以帮助我们快速的进步

主席曰:自己动手,丰衣足食
数据分析看起来很酷,但是学好数据分析不容易。看了老师的代码以后,还是要自己动手演练才能真
正掌握,要不然就是看老师炫技了。

学习目标

学习内容

效果展示

代码与数据分享

Github 地址 https://github.com/huangkai31/ncovanalysis

数据分析常用库 Pandas 简介

数据可视化库 Seaborn 简介

地理可视化库 Folium 简介

1. 建立开发环境

1.1 安装 Folium

# 安装 folium
# ! pip install folium --user

1.2 导入 pandas 等需要的库

# 导入pandas 等
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 忽略警告信息
import warnings
warnings.filterwarnings('ignore')

import folium

# 设置中文字体 kesci 专用代码
plt.rcParams['font.sans-serif'].insert(0, 'Microsoft YaHei')

print('成功建立开发环境')

成功建立开发环境

2. 使用 pandas 读取并处理数据

# 读取疫情数据,查看基本情况
df = pd.read_csv('./data/COVID-19/DXYArea.csv')
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 27521 entries, 0 to 27520
Data columns (total 11 columns):
 #   Column                   Non-Null Count  Dtype 
---  ------                   --------------  ----- 
 0   provinceName             27521 non-null  object
 1   cityName                 27521 non-null  object
 2   province_confirmedCount  27521 non-null  int64 
 3   province_suspectedCount  27521 non-null  int64 
 4   province_curedCount      27521 non-null  int64 
 5   province_deadCount       27521 non-null  int64 
 6   city_confirmedCount      27521 non-null  int64 
 7   city_suspectedCount      27521 non-null  int64 
 8   city_curedCount          27521 non-null  int64 
 9   city_deadCount           27521 non-null  int64 
 10  updateTime               27521 non-null  object
dtypes: int64(8), object(3)
memory usage: 2.3+ MB
df.head()
provinceNamecityNameprovince_confirmedCountprovince_suspectedCountprovince_curedCountprovince_deadCountcity_confirmedCountcity_suspectedCountcity_curedCountcity_deadCountupdateTime
0浙江省温州10750190044807102020-02-09 15:37:28.105
1浙江省杭州10750190016504102020-02-09 15:37:28.105
2浙江省宁波10750190014601302020-02-09 15:37:28.105
3浙江省台州10750190013802702020-02-09 15:37:28.105
4浙江省金华1075019005301302020-02-09 15:37:28.105

2.1 按省份统计确诊人数

# 按省份统计确诊人数
province_confirmedCount = df.groupby('provinceName').province_confirmedCount.agg('max')
province_confirmedCount
provinceName
上海市           293
云南省           140
内蒙古自治区         54
北京市           326
吉林省            78
四川省           386
天津市            90
宁夏回族自治区        45
安徽省           779
山东省           435
山西省           115
广东省          1120
广西壮族自治区       195
新疆维吾尔自治区       45
江苏省           468
江西省           740
河北省           206
河南省          1033
浙江省          1075
海南省           128
湖北省         27100
湖南省           838
澳门              2
甘肃省            79
福建省           250
西藏自治区           1
贵州省            96
辽宁省           105
重庆市           446
陕西省           208
青海省            18
黑龙江省          307
Name: province_confirmedCount, dtype: int64

2.2 读取城市坐标数据

# 读取城市坐标数据
coord = pd.read_csv('./data/COVID-19/china_coordinates.csv', 
  names=['postcode', 'city', 'lon', 'lat'])
coord.head(10)
postcodecitylonlat
0110000北京市116.39564539.929986
1110101东城区113.61283837.857865
2110102西城区113.61283837.857865
3110105朝阳区116.52169539.958953
4110106丰台区116.25837039.841938
5110107石景山区116.18455639.938867
6110108海淀区116.23967840.033162
7110109门头沟区115.79579540.000893
8110111房山区115.86283639.726753
9110112通州区116.74007939.809815

2.3 合并城市坐标数据与省份疫情数据

# 合并城市坐标数据 与 省份疫情数据
coord['confirm'] = coord['city']
coord['confirm'] = coord['confirm'].map(province_confirmedCount.to_dict() )
coord.head()
postcodecitylonlatconfirm
0110000北京市116.39564539.929986326.0
1110101东城区113.61283837.857865NaN
2110102西城区113.61283837.857865NaN
3110105朝阳区116.52169539.958953NaN
4110106丰台区116.25837039.841938NaN

2.4 清洗数据,去掉空值

# 清洗数据,去掉空值
df_prov = coord.dropna()
df_prov
postcodecitylonlatconfirm
0110000北京市116.39564539.929986326.0
17120000天津市117.21081339.14393090.0
33130000河北省115.66143438.613840206.0
214140000山西省112.51549637.866566115.0
345150000内蒙古自治区114.41586843.46823854.0
461210000辽宁省122.75359241.621600105.0
575220000吉林省126.26287643.67884678.0
645230000黑龙江省128.04741447.356592307.0
787310000上海市121.48789931.249162293.0
804320000江苏省119.36848933.013797468.0
913330000浙江省119.95720229.1594941075.0
1015340000安徽省117.21600531.859252779.0
1136350000福建省117.98494326.050118250.0
1231360000江西省115.67608227.757258740.0
1343370000山东省118.52766336.099290435.0
1496410000河南省113.48680434.1571841033.0
1673420000湖北省112.41056231.20931627100.0
1788430000湖南省111.72066427.695864838.0
1925440000广东省113.39481823.4080041120.0
2065450000广西壮族自治区108.92427423.552255195.0
2191460000海南省109.73375519.180501128.0
2192460000海南省109.73375519.180501128.0
2219500000重庆市106.53063529.544606446.0
2220500000重庆市106.53063529.544606446.0
2258510000四川省102.89916030.367481386.0
2458520000贵州省106.73499626.90282696.0
2555530000云南省101.59295224.864213140.0
2700540000西藏自治区89.13798231.3673151.0
2781610000陕西省109.50378935.860026208.0
2898620000甘肃省102.45762538.10326779.0
2999630000青海省96.20254435.49976118.0
3051640000宁夏回族自治区106.15548137.32132345.0
3079650000新疆维吾尔自治区85.61489942.12700145.0

2.5 步骤总结

  • 安装 Folium : pip install folium --user
  • 导入 pandas 等需要的库
  • 使用 pandas 读取并处理数据 :
    • read_csv
    • 分组聚合计算: groupby, agg
    • to_dict , map , dropna

3. Folium 进行基于地理的数据可视化展示

3.1 读取json地理信息文件

# 读取json文件
import json
with open(r'./data/COVID-19/100000_full.json', encoding='utf-8') as f:
    json_data = json.load(f)

3.2 使用 folium 绘制中国轮廓图

3.3 使用 folium 根据疫情数据绘制图表

# 绘制地图 : location 地图中心位置坐标(纬度lat, 经度lon), zoom_start 地图放大系数
map = folium.Map(location=[39.929986, 116.395645], zoom_start=4)
# 取对数解决色彩条不均衡问题
df_prov['logconfirm'] = np.log(df_prov['confirm'])
folium.Choropleth(
    name='疫情热图',  # 名称
    geo_data=json_data,  # 数据文件
    data=df_prov.set_index(df_prov.city),  # 数据集
    columns=['city', 'logconfirm'],  # 列名称
    key_on='feature.properties.name',  # 匹配geo_data 中的属性值
    fill_color='Reds',  # 色彩配置
    # bins = [0, 100, 500, 1000, 10000, 30000]  # 数据区间范围
).add_to(map)

# 将确诊人数增加到地图上
for d in df_prov.itertuples():
    folium.Marker(
        location=[d.lat, d.lon],
        icon=folium.Icon(color='red') if d.confirm > 1000 else
        (folium.Icon(color='orange') if d.confirm >
         100 else folium.Icon(color='blue')),
        tooltip=" {} 确诊 {} 例".format(d.city, int(d.confirm))
    ).add_to(map)
map

3.4 步骤总结

  • 使用 folium 绘制中国轮廓图
    • Choropleth: key_on 参数
    • 取对数解决数据分布问题
  • 使用 folium 根据疫情数据绘制图表
    • Marker
    • itertuples

4. Pandas+Seaborn 进行时序分析与可视化展示

4.1 转换为时序数据

# 转换为时序数据
df['updateTime'] = pd.to_datetime(df['updateTime'])
df.index = pd.DatetimeIndex( df['updateTime'])
df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 27521 entries, 2020-02-09 15:37:28.105000 to 2020-01-24 03:50:31.353000
Data columns (total 11 columns):
 #   Column                   Non-Null Count  Dtype         
---  ------                   --------------  -----         
 0   provinceName             27521 non-null  object        
 1   cityName                 27521 non-null  object        
 2   province_confirmedCount  27521 non-null  int64         
 3   province_suspectedCount  27521 non-null  int64         
 4   province_curedCount      27521 non-null  int64         
 5   province_deadCount       27521 non-null  int64         
 6   city_confirmedCount      27521 non-null  int64         
 7   city_suspectedCount      27521 non-null  int64         
 8   city_curedCount          27521 non-null  int64         
 9   city_deadCount           27521 non-null  int64         
 10  updateTime               27521 non-null  datetime64[ns]
dtypes: datetime64[ns](1), int64(8), object(2)
memory usage: 2.5+ MB

4.2 取出各个省份每天的数据

# 取出各个省份每天的数据
df_provconfirm = df[ ['provinceName', 'province_confirmedCount'] ].groupby([df.index.date, 'provinceName']).first()
df_provconfirm.head()
province_confirmedCount
provinceName
2020-01-24云南省5
内蒙古自治区2
北京市36
吉林省3
四川省15

4.3 计算并绘制全国确诊病例总数线形图

# 对数据进行按天汇总 sum
# unstack 讲省份由索引变为列
# fillna 填充空值
# sum 按行(axis=1)求和 (汇总)
# plot.line 绘制线形图
df_provconfirm.unstack().fillna(value=0).sum(axis=1).plot.line(figsize=(20,8), marker='o')

# 使用 seaborn
sns.set()
plt.figure( figsize=(20, 8))
sns.lineplot(data=df_provconfirm.unstack().fillna(value=0).sum(axis=1), marker = 'o' )

4.4 计算并绘制全国确诊病例增长线形图

df_totalconfirm = df_provconfirm.unstack().fillna(value=0).sum(axis=1)
df_totalconfirm.head()
2020-01-24     866.0
2020-01-25    1324.0
2020-01-26    2019.0
2020-01-27    2838.0
2020-01-28    4601.0
dtype: float64
pd.DataFrame( [df_totalconfirm, df_totalconfirm.diff()]).T.fillna(value=0)\\
.plot.line(figsize=(20,8), marker='o', subplots=True)

4.5 绘制湖北省确诊病例与增长趋势线形图

湖北省数据

# 湖北省数据
df_hubei = df_provconfirm.unstack()[ [('province_confirmedCount', '湖北省')] ].sum(axis=1)
pd.DataFrame( [df_hubei, df_hubei.diff()]).T.fillna(value=0)\\
.plot.line(figsize=(20,8), marker='o', subplots=True)

4.6 绘制非湖北省确诊病例与增长趋势线形图

# 非湖北省数据
df_nhubei = df_provconfirm.unstack().drop(('province_confirmedCount', '湖北省'), axis=1 ).fillna(value=0).sum(axis=1)
pd.DataFrame( [df_nhubei, df_nhubei.diff()]).T.fillna(value=0)\\
.plot.line(figsize=(20,8), marker='o', subplots=True)

4.7 步骤总结

  • 计算并绘制全国确诊病例总数线形图
  • 计算并绘制全国确诊病例增长线形图
  • 分别绘制湖北省 与 非湖北省确诊病例与增长趋势线形图
    • groupby, first, sum
    • unstack, fillna, drop
    • T
    • plot

5. Seaborn 绘制热力图展示疫情热点区域

5.1 扩散指数

扩散指数 = 当天新增确诊病例数 相对于前一天的现有病例数的增长率

# 扩散指数 = 当天新增确诊病例数 相对于前一天的现有病例数的增长率
# 城市名称 
df['city'] = df['provinceName'] + df['cityName']

# 按日期分组计算每个城市的确诊数量
df_cityconfirm = df[ ['city', 'city_confirmedCount']].groupby([df.index.date, 'city']).first().unstack().fillna(value=0)
# 翻转
df_cityconfirm = df_cityconfirm.T
df_cityconfirm.head()
2020-01-242020-01-252020-01-262020-01-272020-01-282020-01-292020-01-302020-01-312020-02-012020-02-022020-02-032020-02-042020-02-052020-02-062020-02-072020-02-082020-02-09
city
city_confirmedCount上海市嘉定0.00.00.00.01.02.02.02.00.00.00.00.00.00.00.00.00.0
上海市嘉定区0.00.00.01.01.00.00.02.02.02.02.03.04.04.05.06.07.0
上海市外地来沪人员0.00.00.023.033.047.051.062.073.074.079.081.086.089.093.096.097.0
上海市奉贤0.00.00.00.01.05.05.05.00.00.00.00.00.00.00.00.00.0
上海市奉贤区0.00.00.01.01.00.00.05.05.05.05.06.07.08.09.09.09.0

5.2 计算差额

# 计算差额 按行计算差额 axis=1
df_cityconfirm.diff(axis=1).head()
2020-01-242020-01-252020-01-262020-01-272020-01-282020-01-292020-01-302020-01-312020-02-012020-02-022020-02-032020-02-042020-02-052020-02-062020-02-072020-02-082020-02-09
city
city_confirmedCount上海市嘉定NaN0.00.00.01.01.00.00.0-2.00.00.00.00.00.00.00.00.0
上海市嘉定区NaN0.00.01.00.0-1.00.02.00.00.00.01.01.00.01.01.01.0
上海市外地来沪人员NaN0.00.023.010.014.04.011.011.01.05.02.05.03.04.03.01.0
上海市奉贤NaN0.00.00.01.04.00.00.0-5.00.00.00.00.00.00.00.00.0
上海市奉贤区NaN0.00.01.00.0-1.00.05.00.00.00.01.01.01.01.00.00.0

5.3 取出第二行数据 单独计算扩散指数

# 取出第二行数据 单独计算扩散指数
v = df_cityconfirm.values[2]
v_diff = df_cityconfirm.diff(axis=1).values[2]
print(10/23) # 手工计算
print(14/33) 
0.43478260869565216
0.42424242424242425
# 处理 v_diff, 去掉第一个数值, 在最后增加一个数值(0)
v_diff = v_diff[1:]
v_diff = np.append(v_diff, 0)
v_diff
array([ 0.,  0., 23., 10., 14.,  4., 11., 11.,  1.,  5.,  2.,  5.,  3., 4.,  3.,  1.,  0.])
# 计算扩散指数
v_diff / v
array([       nan,        nan,        inf, 0.43478261, 0.42424242,
           0.08510638, 0.21568627, 0.17741935, 0.01369863, 0.06756757,
           0.02531646, 0.0617284 , 0.03488372, 0.04494382, 0.03225806,
           0.01041667, 0.        ])

5.4 计算扩散指数

# 计算扩散指数
df_tmp = df_cityconfirm.diff(axis=1)
df_kuosan = df_cityconfirm.copy()

index = 0
for v in df_cityconfirm.values:
    v_diff = df_tmp.values[index]
    df_kuosan.values[index] = np.append(v_diff, 0)[1:]/v
    index += 1
    

5.5 数据处理-清除空值

# 进一步处理,清除空值
df_kuosan = df_kuosan.replace([np.inf, -np.inf], np.nan).fillna(value=0)
df_kuosan.head()
2020-01-242020-01-252020-01-262020-01-272020-01-282020-01-292020-01-302020-01-312020-02-012020-02-022020-02-032020-02-042020-02-052020-02-062020-02-072020-02-082020-02-09
city
city_confirmedCount上海市嘉定0.00.00.00.0000001.0000000.0000000.000000-1.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0
上海市嘉定区0.00.00.00.000000-1.0000000.0000000.0000000.0000000.0000000.0000000.5000000.3333330.0000000.2500000.2000000.1666670.0
上海市外地来沪人员0.00.00.00.4347830.4242420.0851060.2156860.1774190.0136990.0675680.0253160.0617280.0348840.0449440.0322580.0104170.0
上海市奉贤0.00.00.00.0000004.0000000.0000000.000000-1.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0
上海市奉贤区0.00.00.00.000000-1.0000000.0000000.0000000.0000000.0000000.0000000.2000000.1666670.1428570.1250000.0000000.0000000.0

5.6 处理索引列

# 处理索引列以上是关于新型冠状病毒数据可视化分析的主要内容,如果未能解决你的问题,请参考以下文章

数据可视化丨陕西累计确诊184例,新增11例

陕西新型冠状肺炎病例数据可视化及分析

《银川市肺炎疫情及高风险人群数据可视化分析报告》发布 大数据帮助您科学防御疫情

2019-nCoV新型冠状病毒

做好新型冠状病毒防疫 |春节第一重任:说服爸妈带口罩

HTML+CSS+JS实现 ❤️新型冠状病毒射击小游戏❤️