100行代码实现疫情地图可视化

前言

这个春节,大家都在密切关注着疫情的进展。不少人每天醒来打开手机的第一件事,便是查看家乡的疫情图。你所看到的可能是这样的:


又或者是这样的:


疫情进展牵动着我们的心。作为一名开发者,我们闭门在家为抗击疫情做贡献的同时,也可以继续深耕自己的技术。此文章旨在向大家介绍疫情地图可视化的原理,帮助大家深入理解echart。

核心思路

疫情图的核心在于疫情数据整理以及疫情数据可视化。

疫情数据整理

本文疫情数据是由网易新闻的公开数据整理而成,仅用于demo 展示。数据的具体地址已在代码中说明:此地址是一个 Get 请求,大家可以先拷贝地址到浏览器中查看数据格式。请求成功后服务端响应的数据格式如下(文中仅罗列出我们需要的数据

参数 类型 备注
code int  
msg String  
data Object  

data 里面的参数

参数 类型 备注
list List 各地级市确诊人数

Object 里面的参数

参数 类型 备注
name String 地级市名(简称)
province String 省份
confirm int 确诊人数

疫情数据可视化

地图是数据可视化的一种常用工具,我们用地图来展示疫情的具体分布。本文采用的是开源的 pyecharts 项目,方便开发者用于地图展示。其中,pyecharts 是一个帮助生成 Echarts 图表的类库;而 Echarts 则是百度开源的数据可视化 JS 库,支持折线图、柱状图、散点图、K线图、饼图、雷达图、和弦图、力导向布局图、地图、仪表盘、漏斗图、事件河流图等12类图表,并可以在 PC 和移动设备上流畅地运行,兼容当前绝大部分浏览器。pyecharts 是在 Python 的基础上对 Echarts 所进行的扩展。

原理详解

接下来,本文将为大家详细说明如何搭建环境、整合数据、使用 pyecharts 来做数据可视化以及如何调试项目。

环境搭建

为了快速开发此功能并且尽可能地缩减代码量,此 demo 选择使用 Python 来进行开发。为此,我们应该准备好Python 的开发环境并导入python 基础库。

安装 Python 环境

Mac 上面自带了 Python2.7 ,其他机型的电脑可以参考网上相关的安装教程

安装 pip

pip 是 Python 包管理工具,使用该工具可以快速地对Python 包予以查找、下载、安装、卸载等。如果你是在 python.org上下载的最新版本的安装包,则系统已经自带该工具。此外, Python 2.7.9 + 和 Python 3.4+ 以上版本都自带 pip 工具。可以使用“pip –version”命令行来查看当前 pip 的版本。

如果本机没有 配置Python 环境的,我们可以在线安装,只需要在终端输入以下 2 行命令即可


$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ sudo python get-pip.py
  • 1
  • 2
  • 3

安装工程所需要的插件

在代码中大家不难发现我们导入了一些开源的库:

import math
import time
from fake_useragent import UserAgent
from pyecharts.charts import Map
from pyecharts import options as opts
import requests
import json
import sys
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

请求网络数据需要用到的插件:

pip install fake_useragent # 伪装请求,随机生成UserAgent
pip install requests # HTTP请求库。
  • 1
  • 2

地图展示需要用到的插件:

pip install echarts-countries-pypkg  # 世界地图
pip install echarts-china-provinces-pypkg  # 中国省级地图
pip install echarts-china-cities-pypkg  # 中国城市地图
  • 1
  • 2
  • 3

我们把上述的命令行复制到终端,逐行执行即可。

数据整合& 过滤

代码依然简洁明了,我们可以直接使用 requests 库构建一个 GET 请求,服务器响应的数据即为“ 全国所有城市的疫情情况”。

ua = UserAgent(verify_ssl=False)
headers = {‘User-Agent‘: ua.random}
url = "https://c.m.163.com/ug/api/wuhan/app/index/feiyan-data-list?t=1580469818264"

def getEpidemicInfo(url):
    try:
        response = requests.get(url, headers=headers)
        print(response.status_code)
        if response.status_code == 200:
            content_field = json.loads(response.text)
            epidemicInfo = content_field[‘data‘][‘list‘]
            return epidemicInfo
        else:
            print(‘请求错误码:‘ + response.status_code)
            return None
    except Exception as e:
        print(‘此页有问题!‘, e)
        return None
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

请求地址里面的 t 代表时间戳。我们输入上述代码,计算机便会输出前文所提及格式的数据。注意:拿到数据后还要进行过滤,我们仅需获得某个省份、自治州所包含的地级市或者是某个直辖市所包含的下属区县的疫情信息即可。
通过以下代码,我们对有关数据予以筛选:

# 生成本省疫情列表
def makedict(list):
    cityList = {}
    for item in list:
        for k, v in item.items():
        # 1
            if v == sys.argv[1]:
            #2
                if str(item["confirm"]).isdigit():
                # 3
                    if v == "北京" or v == "上海" or v == "天津":
                        cityList[item[‘name‘] + ‘区‘] = int(item["confirm"])
                    elif "自治州" in v:
                        continue
                    else:
                        cityList[item[‘name‘] + ‘市‘] = int(item["confirm"])
    return cityList
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  1. sys.argv[1] 是一个传参,代表我们手动输入的省份、自治区、直辖市或特别行政区,比如浙江、新疆、北京、香港等;
  2. “confirm” 关键字用于匹配响应结果的 value 值,在上文疫情数据整合里有提及,代表当前城市的疫情人数;
  3. pyecharts 是根据城市的全称来适配的,此处需对数据格式中的地级市或者是下属区县进行排查,如果有城市采用简称的,需要进行调试,(如接口返回的城市名是恩施,我们则需要适配成恩施土家族苗族自治州),从而防止地图展示异常。

举例来讲,当我们输入浙江时,计算机最后输出的数据格式为:

{‘湖州市‘: 9, ‘丽水市‘: 16, ‘舟山市‘: 7, ‘衢州市‘: 15, ‘金华市‘: 47, ‘嘉兴市‘: 30, ‘绍兴市‘: 33, ‘宁波市‘: 126, ‘台州市‘: 124, ‘杭州市‘: 151, ‘温州市‘: 396}
  • 1

数据可视化

这是最核心的一步。makeEpidemicInfoMap方法里面的 dict 对应我们过滤得到的数据:

def makeEpidemicInfoMap(dict):

    # 省和直辖市
    province_distribution = dict
    value = province_distribution.values()
    print(province_distribution)
    title = str(int(time.strftime("%Y%m%d")) - 1) + sys.argv[1] + "疫情地图"
    epidemicCount = []
    for k, v in dict.items():
        epidemicCount.append(v)
    # 1
    epidemicCount.sort(reverse=True)
    maxEpidemic = handle(epidemicCount.pop(0))
    maxEpidemic = int(maxEpidemic)
    # 2
    map = Map()
    # 3
    map.set_global_opts(
        title_opts=opts.TitleOpts(title=title),
        visualmap_opts=opts.VisualMapOpts(max_=200, is_piecewise=True,
                                          pieces=[
                                              {"max": 9999999, "min": maxEpidemic, "label": ">" + str(maxEpidemic),
                                               "color": "#780707"},  # 数据范围分段,分颜色,可以根据数据大小具体分配大小
                                              {"max": int(maxEpidemic), "min": int(maxEpidemic / 8) * 7,
                                               "label": str(int(maxEpidemic / 8) * 7) + "-" + str(int(maxEpidemic)),
                                               "color": "#B40404"},
                                              {"max": int(maxEpidemic / 8) * 7, "min": int(maxEpidemic / 8) * 4,
                                               "label": str(int(maxEpidemic / 8) * 4) + "-" + str(
                                                   int(maxEpidemic / 8) * 7 - 1), "color": "#CD1111"},
                                              {"max": int(maxEpidemic / 8) * 4, "min": int(maxEpidemic / 8),
                                               "label": str(int(maxEpidemic / 8)) + "-" + str(
                                                   int(maxEpidemic / 8) * 4 - 1), "color": "#F68181"},
                                              {"max": int(maxEpidemic / 8), "min": 1,
                                               "label": "1-" + str(int(maxEpidemic / 8)), "color": "#F5A9A9"},
                                              {"max": 0, "min": 0, "label": "0", "color": "#FFFFFF"},
                                          ], )  # 最大数据范围,分段
    )
    # 4
    map.add(title, data_pair=province_distribution.items(), maptype=sys.argv[1], is_roam=True)
    map.render(sys.argv[1] + ‘疫情地图.html‘)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  1. 根据所选省份各城市的确诊人数对所有城市进行降序并得到当前省份确诊人数最多的城市名称。maxEpidemic 是最接近该城市确诊人数的高位数,比如当前省份疫情最为严重的城市的确诊数量为“357”,则 maxEpidemic=300 ,引入此参数的目的是让地图呈现效果更加清晰直观。
  2. 用PyEcharts绘制地图需要对Map对象进行初始化,以用于地理区域数据的可视化。
  3. 以建造者模式对 map 进行设值,其中,VisualMapOpts 是 PyEcharts 的视觉映射配置项。
    # 指定 visualMapPiecewise 组件的最大值。
    max =100
    # 是否为分段型
    is_piecewise: bool = False,

    # 自定义的每一段的范围,以及每一段的文字,以及每一段的特别的样式。例如:
    # pieces: [
    #   {"min": 1500}, // 不指定 max,表示 max 为无限大(Infinity)。
    #   {"min": 900, "max": 1500},
    #   {"min": 310, "max": 1000},
    #   {"min": 200, "max": 300},
    #   {"min": 10, "max": 200, "label": ‘10 到 200(自定义label)‘},
    #   {"value": 123, "label": ‘123(自定义特殊颜色)‘, "color": ‘grey‘}, //表示 value 等于 123 的情况
    #   {"max": 5}     // 不指定 min,表示 min 为无限大(-Infinity)。
    # ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

详细配置可以见 PyEcharts 官网。此处的范围分为6 段,每一段的范围均是根据上述计算出来的 maxEpidemic 进行动态调整的,目的是为了保证疫情图的视觉效果,这里面我仅是做了非常简略的范围模型,仅供参考
4. 使用 PyEcharts 在当前目录下面生成一个网页

调试

执行 python map.py [省份],如:

python /Users/xxx/map.py 浙江
  • 1
  • 2

会在当前目录下面得到一份名字为 浙江疫情地图.html 的文件,直接使用浏览器打开即可,最后的展示效果是不是很酷


总结

读完此篇文章,希望大家可以对数据可视化有个初步的了解。全民战“疫”期间,个推服务的脚步不会停歇,我们将一如既往地为开发者提供技术支持。此外,个推“防灾速报”小程序还上线了 “新型肺炎疫情实时动态”新功能,为大家进行疫情防护提供可靠的数据支持。

原文地址:https://www.cnblogs.com/xiaohuhu/p/12395354.html

时间: 2024-11-09 03:15:43

100行代码实现疫情地图可视化的相关文章

100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)【转】

转自:http://blog.csdn.net/leixiaohua1020/article/details/8652605 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 简介 流程图 simplest_ffmpeg_player标准版代码 simplest_ffmpeg_player_suSU版代码 结果 FFMPEG相关学习资料 补充问题 ===================================================== 最简单的基于FFmp

GameBuilder开发游戏应用系列之100行代码实现贪吃蛇

在线预览:http://osgames.duapp.com/apprun.html?appid=osgames1-801422234293697 在线编辑:http://osgames.duapp.com/gamebuilder.php?appid=osgames1-801422234293697 微信扫描: 运行截图: 除了重力感应游戏,GameBuilder开发传统的游戏也毫不逊色,作为一个怀旧的人,总是对这类游戏情有独钟. 贪吃蛇主要靠一个[UICanvas]来实现,前面一片博客GameB

用JavaCV改写“100行代码实现最简单的基于FFMPEG+SDL的视频播放器 ”

FFMPEG的文档少,JavaCV的文档就更少了.从网上找到这篇100行代码实现最简单的基于FFMPEG+SDL的视频播放器.地址是http://blog.csdn.net/leixiaohua1020/article/details/8652605. 用JavaCV重新实现并使用opencv_highgui进行显示. 1 import com.googlecode.javacpp.IntPointer; 2 import com.googlecode.javacpp.Pointer; 3 im

不到100行代码实现一个推荐系统

似乎咱的产品七,八年前就想做个推荐系统的,就是类似根据用户的喜好,自动的找到用户喜欢的电影或者节目,给用户做推荐.可是这么多年过去了,不知道是领导忘记了还是怎么了,连个影子还没见到. 而市场上各种产品的都有了推荐系统了.比如常见的各种购物网站京东,亚马逊,淘宝之类的商品推荐,视频网站优酷的的类似影片推荐,豆瓣音乐的音乐推荐...... 一个好的推荐系统推荐的精度必然很高,能够真的发现用户的潜在需求或喜好,提高购物网詀的销量,让视频网站发现用户喜欢的收费电影... 可是要实现一个高精度的推荐系统不

不到100行代码实现一个简单的推荐系统

似乎咱的产品七,八年前就想做个推荐系统的,就是类似根据用户的喜好,自动的找到用户喜欢的电影或者节目,给用户做推荐.可是这么多年过去了,不知道是领导忘记了还是怎么了,连个影子还没见到. 而市场上各种产品的都有了推荐系统了.比如常见的各种购物网站京东,亚马逊,淘宝之类的商品推荐,视频网站优酷的的类似影片推荐,豆瓣音乐的音乐推荐...... 一个好的推荐系统推荐的精度必然很高,能够真的发现用户的潜在需求或喜好,提高购物网詀的销量,让视频网站发现用户喜欢的收费电影... 可是要实现一个高精度的推荐系统不

100行代码教你教务系统自动抢课!

帮助广大学生解决抢课问题!自动抢课!! 100行代码帮你实现抢课! ? 本项目使用了python中splinter的API接口用来操作页面交互,用了twilio用来给手机发送短信通知抢课成功. ? 欢迎大家来全球最大同性交友网站Github:https://github.com/xubin97 来fork我的菜鸡代码,希望你能来继续增加更多功能,我也会不定期更新功能! ? 其中splinter API文档链接:https://splinter.readthedocs.io/en/latest/m

100行代码实现简单目录浏览器制作

给大家分享使用Lae软件开发工具开发小应用程序的过程,希望大家喜欢! 界面部分我们用lae软件开发工具实现,无需写代码,业务逻辑部分使用Lae软件开发平台自带的LuaIDE编辑器,使用100行lua代码完成简单目录浏览器的制作. lae软件下载地址: https://github.com/ouloba/laetool.git lae软件下载地址(国内):https://pan.baidu.com/s/1ckMy0Q 相关视频: http://www.tudou.com/listplay/aly7

基于zbus网络通讯模块实现的MySQL透明代理(<100行代码)

项目地址 https://git.oschina.net/rushmore/zbus 我们上次讲到zbus网络通讯的核心API: Dispatcher -- 负责-NIO网络事件Selector引擎的管理,对Selector引擎负载均衡 IoAdaptor -- 网络事件的处理,服务器与客户端共用,负责读写,消息分包组包等 Session -- 代表网络链接,可以读写消息 实际的应用,我们几乎只需要做IoAdaptor的个性化实现就能完成高效的网络通讯服务,今天我们将举例说明如何个性化这个IoA

100 行代码实现的 JavaScript MVC 样式框架

介绍 使用过 JavaScript框架(如 AngularJS, Backbone 或者Ember)的人都很熟悉在UI(用户界面,前端)中mvc的工作机理.这些框架实现了MVC,使得在一个单页面中实现根据需要变化视图时更加轻松,而模型-视图-控制器(mvc)的核心概念就是:处理传入请求的控制器.显示信息的视图.表示业务规则和数据访问的模型. 因此,当需要创建这样一个需要在单个页面中实现切换出不同内容的应用时,我们通常选择使用上述框架之一.但是,如果我们仅仅需要一个在一个url中实现视图切换的框架