Python绘制全球疫情变化地图的实例代码

作者:渡码 时间:2022-08-27 07:06:46 

目前全球疫情仍然比较严重,为了能清晰地看到疫情爆发以来至现在全球疫情的变化趋势,我绘制了一张疫情变化地图 废话不多说,先上图

Python绘制全球疫情变化地图的实例代码

下面就来重点介绍下上面这张图的绘制过程,主要分为以下三个步骤:

  • 数据收集

  • 数据处理

  • 画图

下面一个一个来说。

数据收集

这是万里长城的第一步,俗话说“巧妇难为无米之炊”,既然是变化图,当然需要每个国家、每天的现有确诊病例数。好在现在各大网站都有疫情相关的专题页,我们可以直接抓数据。以网易为例

Python绘制全球疫情变化地图的实例代码

我们选择 XHR,重新刷新下网页可以看到有几个接口,其中 list-total 接口是获取当前所有有疫情的国家,以及对应的国家id。另外,我们看到还有一个 list-by-area-code 接口,它是获取每个国家历史上每天的疫情数据,请求这个接口需要带 areaCode 参数,这个参数就是我们刚刚说的国家id。所以对我们来说这两个接口是最重要的。下面我们就看看请求 list-total 接口的代码


def get_and_save_all_countries():
"""
获取所有的国家名以及对应的id,保存为文件
"""

url = 'https://c.m.163.com/ug/api/wuhan/app/data/list-total?t=317452696323'
list_total_req = requests.get(url, headers=headers)
if list_total_req.status_code == 200:
area_tree = list_total_req.json()['data']['areaTree']

area_dict = {}
for area in area_tree:
 country_id = area['id']
 name = area['name']
 area_dict[country_id] = name

area_json = json.dumps(area_dict, ensure_ascii=False) # ensure_ascii=False 防止json编码后中文编程\u开头的字符
write_file('./config/countries_id2name.json', area_json)

这里将请求下来的数据临时存放在文件里。有了所有的疫情国家的id,我们就可以请求 list-by-area-code 接口来获取每个国家的疫情数据了。代码与上面的类似,不同的是将请求结果存在了 mongodb 而不是文件,目的是为了方便增删改查。当然为了大家方便使用,我将mongodb中的数据导入了文件 counties_daily.json 中,大家可以在源码根目录找到它。

数据处理

这一步的处理主要是为第三步画图做准备的。因为我们画图用的是pyecharts框架,它绘制世界地图需要输入的国家名是英文的,而我们收集的国家名是中文的,所以要将中文国家名对应到英文国家名。最终的效果如下

Python绘制全球疫情变化地图的实例代码

网上能找到这样的对应关系,但想要用起来还需要解决两个问题。第一,两边中文名统一,比如:我们收集的国家名是中非共和国,而对应关系里是中非,那还是对应不上。第二,需要自己增加映射关系,网上找的一般都不全,我们需要根据收集的数据自行增加。经过上面两个步骤处理后,我们就可以将大部分国家名对应到pyechars能识别的英文名了。相关代码如下


def get_cy_properties():
# 获取配置文件信息
countries_id2name = read_file('./config/countries_id2name.json')
cy_id2name_dict = json.loads(countries_id2name)
cy_ch2en = {v: k for k, v in countries_dict.items()}

# 调整国家的名字与配置文件一致
cy_id2name_dict['879'] = '波斯尼亚和黑塞哥维那'
cy_id2name_dict['8102'] = '多哥'
cy_id2name_dict['8143'] = '刚果民主共和国'
cy_id2name_dict['95983'] = '刚果'
cy_id2name_dict['8144'] = '中非'
cy_id2name_dict['95000011'] = '多米尼加'

cy_props = {}
for key in cy_id2name_dict:
cy_name = cy_id2name_dict[key]
if cy_name in cy_ch2en:
 cy_props[cy_name] = {}
 cy_props[cy_name]['id'] = key
 cy_props[cy_name]['en_name'] = cy_ch2en[cy_name]

return cy_props

画图

这一步涉及到两个核心过程——构造数据结构和画图。首先,我构造了3个数据结构,分别是date_list、cy_name_list 和 ncov_data。date_list存放的是日期列表,因为我们画动图,所以需要一段时间;cy_name_list 存放收集的所有国家列表(英文名);ncov_data是一个字典,key是日期,value是数组,存放各个国家当天的确诊病例数。生成这三个数据结构的代码如下


def parse_ncov_data(start_date, end_date, records):
if not records:
 return

date_list = get_date_range(start_date, end_date)
cy_name_list = []
res = {}
# 获取各国每天现有确认病例
for i, record in enumerate(records):
 cy_name = record['cy_en_name']
 cy_name_list.append(cy_name)

# 解析每天数据并计算现有确认病例
 existing_case_dict = {}
 for ncov_daily in record['data']['list']:
  date_str = ncov_daily['date']
  confirm = ncov_daily['total']['confirm'] # 累计确诊
  heal = ncov_daily['total']['heal'] # 累计确诊
  dead = ncov_daily['total']['dead'] # 累计死亡

existing_case = confirm - heal - dead
  existing_case_dict[date_str] = existing_case

last_existing_case = 0
 # 将每天确诊病例数合并到res中
 for date_str in date_list:
  if date_str not in res: # 初始化
   res[date_str] = []

existing_case = existing_case_dict.get(date_str)
  if existing_case is None:
   existing_case = last_existing_case
  res[date_str].append(existing_case)

last_existing_case = existing_case

return date_list, cy_name_list, res

参数 records 是一个数组,数组每个元素代表一个国家,内容便是我们在第一步请求 list-by-area-code 接口的数据。最后,用 pyecharts 来画图,直接上代码


def render_map(date_list, cy_name_list, ncov_data):
tl = Timeline() # 创建时间线轮播多图,可以让图形按照输入的时间动起来
# is_auto_play:自动播放
# play_interval:播放时间间隔,单位:毫秒
# is_loop_play:是否循环播放
tl.add_schema(is_auto_play=True, play_interval=50, is_loop_play=False)

for date_str in date_list: # 遍历时间列表
 map0 = (
  Map() # 创建地图图表
  # 将国家名 cy_name_list 以及各国当天确诊病例 ncov_data[date_str] 加入地图中
  .add("全球疫情趋势", [list(z) for z in zip(cy_name_list, ncov_data[date_str])],
   "world", is_map_symbol_show=False)
  .set_series_opts(label_opts=opts.LabelOpts(is_show=False)) # 不显示国家名
  .set_global_opts(
   title_opts=opts.TitleOpts(title="%s日" % date_str), # 图表标题
   visualmap_opts=opts.VisualMapOpts(max_=80), # 当确诊病例大于80 ,地图颜色是红色
  )
 )
 tl.add(map0, "%s" % date_str) # 将当天的地图状态加入时间线中

tl.render() # 生成最终轮播多图,会在当前目录创建 render.html 文件

代码里加了注释,这里就不再赘述了。
运行 render_map 函数会在当前目录生成 render.html 文件,打开后便自动播放疫情变化趋势,如文章开头 gif。另外,有些朋友可能会问,能不能直接输出 gif。这一点我也尝试过,百度、谷歌、GitHub上的教程基本上都试了一遍,比较遗憾没有找到靠谱的方法。所以劝大家还是放弃这条路,曲线救国,录制一个视频转成 gif 即可,方便快捷。毕竟人生苦短,Python 为我们节省下的时间不能再被这些无谓的坑再填回去。这样整个过程就介绍完了,虽然思路不复杂,但局部细节上还是需要花一些时间处理的。

完整代码共 230 行,需要的点击下载。

链接: https://pan.baidu.com/s/17nIHelAGviyNhftskB-rdA 提取码: at9z

最近国内某些地方出现了反弹的迹象,希望大家无论是在工作还是生活上都能继续保持警惕。希望这次疫情早点过去,等待全球地图变白的那一天。

来源:https://www.cnblogs.com/duma/p/12735078.html

标签:Python,疫情,地图
0
投稿

猜你喜欢

  • Golang排列组合算法问题之全排列实现方法

    2023-07-14 14:16:19
  • vue使用localStorage保存登录信息 适用于移动端、PC端

    2024-04-30 08:46:25
  • Python中函数参数调用方式分析

    2022-09-14 04:54:07
  • 浅谈keras中的目标函数和优化函数MSE用法

    2022-01-19 02:15:55
  • layui radio单选限制下一个radio单选的实例

    2024-06-09 15:52:07
  • Python使用pydub模块转换音频格式以及对音频进行剪辑

    2023-03-22 02:17:37
  • 利用Django框架中select_related和prefetch_related函数对数据库查询优化

    2024-01-20 23:24:19
  • 关于Pandas count()与values_count()的用法及区别

    2021-09-25 08:28:20
  • 解决Pycharm 导入其他文件夹源码的2种方法

    2023-03-02 08:32:54
  • Python中的CURL PycURL使用例子

    2023-05-13 04:14:31
  • 解析JavaScript中 querySelector 与 getElementById 方法的区别

    2024-04-19 09:57:32
  • AJAX实现延时顺序请求多个URL

    2007-12-06 18:32:00
  • pytorch中使用LSTM详解

    2021-01-08 04:27:10
  • JavaScript中判断的优雅写法示例

    2024-04-10 10:43:46
  • 使用Python实现汉诺塔问题示例

    2022-10-22 09:17:47
  • Python处理json字符串转化为字典的简单实现

    2022-05-15 01:42:58
  • MySQL 去除重复数据实例详解

    2024-01-24 13:21:53
  • 基于Bootstrap使用jQuery实现简单可编辑表格

    2023-08-22 20:15:07
  • Django返回json数据用法示例

    2022-05-25 21:00:52
  • 详解JavaScript的垃圾回收机制

    2024-06-23 18:05:52
  • asp之家 网络编程 m.aspxhome.com