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


Posted in Python onApril 20, 2020

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

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

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

到此这篇关于Python绘制全球疫情变化地图的实例代码的文章就介绍到这了,更多相关Python全球疫情变化地图内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python编写的com组件发生R6034错误的原因与解决办法
Apr 01 Python
Python中关键字is与==的区别简述
Jul 31 Python
Python装饰器decorator用法实例
Nov 10 Python
pandas中的DataFrame按指定顺序输出所有列的方法
Apr 10 Python
利用ctypes获取numpy数组的指针方法
Feb 12 Python
Python判断对象是否相等及eq函数的讲解
Feb 25 Python
Pycharm创建项目时如何自动添加头部信息
Nov 14 Python
Python线程障碍对象Barrier原理详解
Dec 02 Python
python如何变换环境
Jul 21 Python
Python urllib request模块发送请求实现过程解析
Dec 10 Python
在 Python 中使用 7zip 备份文件的操作
Dec 11 Python
python基础之函数的定义和调用
Oct 24 Python
spyder 在控制台(console)执行python文件,debug python程序方式
Apr 20 #Python
python实现小程序推送页面收录脚本
Apr 20 #Python
在spyder IPython console中,运行代码加入参数的实例
Apr 20 #Python
如何查看Django ORM执行的SQL语句的实现
Apr 20 #Python
使用IPython或Spyder将省略号表示的内容完整输出
Apr 20 #Python
解决Python spyder显示不全df列和行的问题
Apr 20 #Python
Python爬虫实现vip电影下载的示例代码
Apr 20 #Python
You might like
让Laravel API永远返回JSON格式响应的方法示例
2018/09/05 PHP
大家未必知道的Js技巧收藏
2008/04/07 Javascript
javascript图像处理—仿射变换深度理解
2013/01/16 Javascript
jQuery的Ajax的自动完成功能控件简要说明
2013/02/22 Javascript
详解JavaScript正则表达式之RegExp对象
2015/12/13 Javascript
js+canvas简单绘制圆圈的方法
2016/01/28 Javascript
javascript结合Flexbox简单实现滑动拼图游戏
2016/02/18 Javascript
jquery mobile界面数据刷新的实现方法
2016/05/28 Javascript
js中class的点击事件没有效果的解决方法
2016/10/13 Javascript
JavaScript 实现的checkbox经典实例分享
2016/10/16 Javascript
JS中的数组转变成JSON格式字符串的方法
2017/05/09 Javascript
vue做网页开场视频的实例代码
2017/10/20 Javascript
浅谈React高阶组件
2018/03/28 Javascript
Vue中使用canvas方法总结
2019/02/12 Javascript
vue实现侧边栏导航效果
2019/10/21 Javascript
分享Angular http interceptors 拦截器使用(推荐)
2019/11/10 Javascript
js实现树形数据转成扁平数据的方法示例
2020/02/27 Javascript
Vue将props值实时传递 并可修改的操作
2020/08/09 Javascript
Vue实现点击导航栏当前标签后变色功能
2020/08/19 Javascript
Python中使用pprint函数进行格式化输出的教程
2015/04/07 Python
Python Pillow Image Invert
2019/01/22 Python
python3+PyQt5 创建多线程网络应用-TCP客户端和TCP服务器实例
2019/06/17 Python
简单了解Java Netty Reactor三种线程模型
2020/04/26 Python
Django+Celery实现动态配置定时任务的方法示例
2020/05/26 Python
python实现猜数游戏(保存游戏记录)
2020/06/22 Python
Python同时迭代多个序列的方法
2020/07/28 Python
html5视频自动横过来自适应页面且点击播放功能的实现
2020/06/03 HTML / CSS
在求职信中如何凸显个人优势
2013/10/30 职场文书
银行员工犯错检讨书
2014/09/16 职场文书
银行柜员与客户起冲突检讨书
2014/09/27 职场文书
办公室主任四风问题对照检查材料思想汇报
2014/09/28 职场文书
教师个人查摆剖析材料
2014/10/14 职场文书
2015年八一建军节演讲稿
2015/03/19 职场文书
《穷人》教学反思
2016/02/19 职场文书
redis 限制内存使用大小的实现
2021/05/08 Redis
总结一下关于在Java8中使用stream流踩过的一些坑
2021/06/24 Java/Android