春江暮客

春江暮客的个人学习分享网站

使用folium绘制新冠肺炎COVID-19疫情地图

2020-05-03 技术
使用folium绘制新冠肺炎COVID-19疫情地图

这篇文章的重点不是疫情结论本身,而是如何把“按国家汇总的公开数据”做成一张可以交互查看的世界地图。对于想练习 foliumChoropleth 和数据预处理的人来说,这类题材很适合上手。

首先 python 绘图库很多,比如 matplotlibpandasplotly 等,但如果目标是快速生成带地理边界的 HTML 地图,folium 仍然非常直接。本文就以全球疫情公开数据为例,演示从数据获取到地图输出的完整流程。

绘制疫情地图主要包含以下步骤:

  • 全球新冠疫情数据获取
  • 绘制世界地图
  • 数据预处理
  • 添加疫情数据到地图
  • 改进疫情地图

使用前说明

这是一篇历史数据可视化教程。类似 WHO 或第三方数据接口在不同年份可能会调整路径、字段名或访问方式,因此如果你今天复现时接口失效,优先检查数据源地址是否已经变更。

如何先验证数据是否拿对了

在正式画图前,建议先确认:

  1. JSON 是否能正常返回
  2. dimensionsmetrics 字段是否还存在
  3. 生成的 DataFrame 是否确实包含国家代码和累计确诊列

例如先跑这几步:

print(covid19_dataframe.columns)
print(covid19_dataframe.head())

如果列名和示例差异很大,通常说明上游接口字段已经变化,需要先调整清洗逻辑。

常见问题

1. 地图生成了,但很多国家都是空白

最常见原因是国家代码映射失败,导致 fullname 和 geojson 里的国家标识对不上。

2. 数据接口请求失败

通常是接口地址变化、访问限制,或者源站字段结构已调整。优先先打印原始 JSON 结构再继续改代码。

3. 地图颜色层级不明显

如果数据跨度很大,直接用原始值做 Choropleth 往往会让大多数地区看起来颜色很浅,这时对数转换通常会更直观。

延伸阅读

全球新冠疫情数据获取

为了获取最新的疫情数据,支付宝早就每天都公布数据了,但是我并没有找到关于疫情数据的api获取方式,通过搜索引擎找到了以下每天更新疫情数据的资源。

来自who的数据当然是最新最可靠的,who数据网站上面点击就可以直接进入了。通过chrome的审查网页查看网络连接信息,找寻到数据api接口为who api who_json_api 这是一个json数据,通过python的json就可以解析了,鉴于这是最权威的发布源,本文采用who的信息来源。 首先安装本文所需用到的必要的包

pip install folium
pip install numpy 
pip install pandas

接下来就是真正的数据获取和处理流程了。


## 下载数据
import requests
import json
covid19_json = requests.get("https://dashboards-dev.sprinklr.com/data/9043/global-covid19-who-gis.json").content
## json 解析数据
covid19_json = json.loads(covid19_json)
##查看数据列名
print(covid19_json['dimensions'])
"""
[{'name': 'day', 'type': 'TIMESTAMP', 'dataType': None},
 {'name': 'Country', 'type': 'STRING', 'dataType': None},
 {'name': 'Region', 'type': 'STRING', 'dataType': None}]
"""

###前三行分别是时间戳,国家,地区
covid19_json['metrics']
"""
[{'name': 'Deaths', 'type': 'NUMBER', 'dataType': None},
 {'name': 'Cumulative Deaths', 'type': 'NUMBER', 'dataType': None},
 {'name': 'Confirmed', 'type': 'NUMBER', 'dataType': None},
 {'name': 'Cumulative Confirmed', 'type': 'NUMBER', 'dataType': None}]

"""
## 后四行分别是当天死亡人数,累积死亡人数,当天确诊数,累积确诊数

根据各行数据是什么最终合成用于分析的dataframe

import pandas as pd

## 列名确定

colname = pd.DataFrame(covid19_json['dimensions'])["name"].append(pd.DataFrame(covid19_json['metrics'])["name"]).to_list()
## 生成dataframe

covid19_dataframe = pd.DataFrame(covid19_json["rows"],columns=colname)

covid19_dataframe.head()
"""

day	Country	Region	Deaths	Cumulative Deaths	Confirmed	Cumulative Confirmed
0	1582502400000	AF	EMRO	0	0	1	1
1	1582588800000	AF	EMRO	0	0	0	1
2	1582675200000	AF	EMRO	0	0	0	1
3	1582761600000	AF	EMRO	0	0	0	1
4	1582848000000	AF	EMRO	0	0	0	1

"""

到这里,实现了从WHO新冠肺炎官网获取到数据并最终生成了python中的DataFrame,其中包括时间,国家,地区,死亡人数,累积死亡人数,确诊人数,累积确诊人数。

绘制世界地图

接下来就是先绘制一个空白的世界地图,用于后续添加确诊人数情况和死亡情况。这里采用前面讲到的folium包,关于该包的任何使用方法和问题请查看folium官方文档. 世界地图的绘制

import folium

m = folium.Map()
m

可以看到已经生成了地图。 folium_map

数据预处理

由于WHO官网获取到的国家代码是简写,为了能够与folium包兼容,我们需要建立一个字典用于处理国家代码简写与folium的国家代码对应,并得到国家边界等信息,这样可以通过颜色等信息表示不同国家的内容并去除掉一些不必要的信息。在folium已经提供了相关的国家geo信息的json数据

## 下载geojson数据

url = "https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/world-countries.json"

# address:https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/world-countries.json
#github 无法连接的话可使用https://www.bobobk.com/wp-content/uploads/2020/05/world-countries.json替换

geojson = json.loads(requests.get(url).content)

关于国家代码的csv文件,已下载,可在本站下载到。

下载地址:

国家代码简写csv文件

将covid-19中的国家代码替换

## map country
df_abb = pd.read_csv("https://www.bobobk.com/wp-content/uploads/2020/05/country_codes.csv",header = None)
dic_abb = {df_abb.iloc[i,1]:df_abb.iloc[i,2] for i in range(np.shape(df_abb)[0])}
covid19_dataframe['fullname'] = covid19_dataframe['Country'].map(dic_abb)
## 简化数据,只需要最新的日期的确诊数据和累积确诊数据

today = str(covid19_dataframe.day.unique().max())
covid19_dataframe[covid19_dataframe.day==today]
covid19_dataframe = covid19_dataframe[["Country","fullname","Cumulative Confirmed","Confirmed"]]

添加疫情数据到地图

接下来就是见证奇迹的时刻了,将从WHO获取到的最新新冠肺炎疫情数据绘制到地图上面,使用的函数的folium.Choropleth,具体实现见以下代码:

## 一条命令就可以了
folium.Choropleth(geo_data=url,name = "covid-19 cumulative confirm map",data = covid19_dataframe,\
                  columns=["fullname","Cumulative Confirmed"],key_on = "feature.id",\
                  fill_color='PuRd',nan_fill_color='white').add_to(m)

累积确诊

total_confirm

参数意义:

  • geo_data 从github下载的url链接,无需下载下来
  • name 网页名称
  • data pandas的dataframe数据表
  • columns 两列,一列为国家代码,需要跟geo_data里面的数据一致,第二列为数字列,这里为累积确诊
  • key_on 表示前面的代码表示的是哪个参数,本文使用的是国家全称,按实例就好了。
  • fill_color 表示数字颜色
  • nan_fill_color 没有数字的地区颜色填充

熟悉了之后,我们继续添加下每日新增的数据地图吧。

m = folium.Map()
folium.Choropleth(geo_data=url,name = "covid-19 confirm map",data = covid19_dataframe,\
                  columns=["fullname","Confirmed"],key_on = "feature.id",\
                  fill_color='PuRd',nan_fill_color='white').add_to(m)
# m.save("new_confirm.html")

新增确诊 new_confirm

改进疫情地图

前面的图虽然可以看到不同地区的确诊数等情况,但是由于数据差距比较大,大部分的国家都只是白色,因此,这里将数字做一个log转换来表示各国情况,这下网页效果好看多了。 绘图使用代码为:

covid19_dataframe["log_total_confirm"] = np.log(covid19_dataframe["Cumulative Confirmed"]+1)
covid19_dataframe["log_new_confirm"] = np.log(covid19_dataframe["Confirmed"]+1)
covid19_dataframe.head()
## log的总确诊数
m = folium.Map()
folium.Choropleth(geo_data=url,name = "covid-19 log total confirm map",data = covid19_dataframe,\
                  columns=["fullname","log_total_confirm"],key_on = "feature.id",
                  fill_color='PuRd',nan_fill_color='white').add_to(m)
m.save("total_confirm_improve.html")
## log 的新增确诊数
m = folium.Map()
folium.Choropleth(geo_data=url,name = "covid-19 log new confirm map",data = covid19_dataframe,\
                  columns=["fullname","log_new_confirm"],key_on = "feature.id",\
                  fill_color='PuRd',nan_fill_color='white').add_to(m)
m.save("new_confirm_improve.html")

结果查看 log后累积确诊 _total_confirm_improve log后新增确诊 new_confirm_improve

在新增情况可以看到非常清楚地看到哪里的确诊数在迅速上升,哪里比较安全。需要特别留意的国家和地区。

总结

本文结合WHO公布的全世界各国及地区的最新疫情数据,通过folium包绘制了各国总确诊数,新增确诊数的疫情地图,方便世界各地区的人员每日获取最新疫情,关注自身健康,少出门,多洗手,戴好口罩,为对抗新冠病毒贡献自己的一份力。

总代码下载地址

python疫情分析代码下载

为每日可以更新信息,本站在tool.bobobk.com上开放每日疫情数据查看,接口地址如下:

友情链接

其它