地图——基于python的gis开发与应用

新冠病毒疫情地图、GIS和Qt平台

这是沁园春里最难的、最核心的部分。没有地图,GIS是玩不转的。没有基石,如何能建起高楼?地图就是gis的基石。我的论文要义是基于python做gis,所以python成了我的制图工具。而python是一个神奇的语言,它的开发者为它和它的忠实编程粉丝设计和开发了各式各样的python包和python库,就只谈制做地图这方面的包和库就有好几种,比如matplotlib、folium、basemap、pyplot、cartopy等等。我前面也提到了,python 2.X版本在2020年被停止维护和升级,而作为python 2.X的殉葬品,basemap等包也得不到更新。但是中国人自己研发的pyecharts是开发地图的神器,适用于python任何版本里,并且我用的是python 3.8版本,所以我就用它来完成这次的地图制作项目。

Pyecharts制作出来的东西是可视化的、有交互性的。Pyecharts输出格式目前所知只有两种:分别为html格式和png格式。但是Pyecharts的交互性只能体现在HTML上,无法将交互性引用到图片中,因此pyecharts可以和一些web框架联动,这是后话,暂且不在这里谈。

另话:制作地图除了像我这样以外,还可以调用API来做。像百度地图、高德地图等地图制作公司都有相关地图制作开发开放平台,是地图爱好者等人的天堂。有了这些API,就可以把python的地图包给省下了,但是要导入urllib包、requests包等跟爬虫相关的包,而且这个制图方式重点不在python身上,而是HTML修改上。所以我没有选择这个方法,这个方法无法体现gis是基于python上。

 制作地图和GIS

Pyecharts由一支国人团队研发,有专门的操作说明,其说明网址是:http://pyecharts.org/#/,他们还特地为编程者设有一个实例网址(专门提供案例供爱好者去研究pyecharts深入学习):http://gallery.pyecharts.org/#/ ,里面有许多令人惊讶到失声的美图和代码,让人流连忘返。

这一步虽说是制作地图,其实不然,地图的制作早就被pyecharts的开发人员给做好了,我只需要调用它即可,然后再给它附上数据,这就成为了我独创独有的地图。

我学到两种制图方法,但皆有缺点:

其一,运用爬虫去爬数据,然后直接调用在地图上显示。

第一步跟爬数据是一样的,找到网站,写下数据包装函数(只写部分重要处):

def catch_cn_disease_dis():

url_area = (‘https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5’ ‘&callback=&_=’) + timestamp

第二步调用pyecharts的地图函数画出地图并把爬来的数据对应地合在地图上:

def map_cn_disease_dis() -> Map:

Map().title_opts 是给地图命名,设置标题。

Map().visualmap_opts 是给地图整理格式,可以设置最大数据范围。

最后一步,把地图输出:

Map_cn_disease_dis().render()

render()是pyecharts的输出函数,只可输出pyecharts已设计好的网页、图片或是notebook(比如Jupyter Notebook、Jupyter Lab和Nteract)输出结果。

结果如下图4.14所示(该示例显示的病毒感染状态时间是2020年4月30日):

地图——基于python的gis开发与应用

 

图4.14 疫情地图20200430

可以不用再写爬数据的代码,但缺点是:当天只能爬当天的数据,之前的数据一概爬不到,而且我也不可能天天爬。

其二,直接读电脑里的相关数据文件,与地图相合。

第一步,除了pyecharts,还要导入pandas。Pandas也是一个神奇的包。我的数据是存在excel里的,一般python调用excel的数据需要下好几个包,而且还要根据excel版本不一样下对应版本的包。Pandas一下子就把这些琐碎的杂事解决了,pandas有一个excel读取函数,无论excel文件后面点缀是.xlsx还是.xls,皆可以读取调用。这个函数是read_excel(),如果被调用的excel里有多个页表,就需要在该函数内标明是哪个页表,用sheet_name=’ ‘来表示。以我的代码为例,如下:

data = pandas.read_excel(‘G:/pycharm/Spider/疫情历史数据(个人整理,非官方提供)/疫情数据2019年12月.xlsx’, sheet_name = ‘2019-12-31’ )    #导入数据

这个意思是读取G盘里pycharm/Spider/疫情历史数据(个人整理,非官方提供)这个文件夹里的名为“疫情数据2019年12月”的excel文件中的名为‘2019-12-31’的页表,因为我在这个excel文件里设置了很多页表,需要单独提出,不然默认读取的是第一个页表或者读取会出错。

第二步,将读取的数据转换为二元的列表,即和pyecharts里地图数据格式相吻合。该列表代码如下所示:

List1 = list(zip(data[‘province’], data[‘confirmed’]))  #将数据转换成二元的列表

我这个excel表里有两列,我分别命名为‘province’和‘confirmed’,分别代表中国的省份和各自省份确诊人数。我就需要这两列数据来做文章、做地图、做GIS。

这第三步跟之前的其一的第二部类似,调用Map()里的set_global_opts()函数,给地图设置标题、设置数据范围。然后再使用add函数添加地图数据和地图类型。如果可以,在做这步之前最好先创建一个地图对象,这样做不怎么会出差错。

最后再用render()函数输出结果。结果如下图4.15所示(该示例显示的疫情时间是2019年12月31日):

地图——基于python的gis开发与应用

 

图4.15 疫情地图20191231

我用这个方法连续做了一百五十多个,从2019年12月1日到2020年4月30日。

这个方法的缺点是:无法做到批量化,做这么多张地图,要一个一个地输入excel文件名,任务量非常重,且这么做容易出错。

目前我没有找到解决这个缺点的办法。

 

 Qt平台

其实做到这里我就已经完成了我的任务。那些疫情地图基本上算是GIS,属于较简单的。我之前也说了,GIS是数据上的地图。我把数据镶嵌在地图里并显示出来,就已经做出了一个GIS。

但是我不满足,我觉得要用一个东西来衬托它,就像用盘子来托住瓜果菜蔬。GUI成了我的首选。我思来想去,我决定使用Qt,虽然这是一个C++编程软件,但它和python有联系、有关联,而且在python中可用GUI编程里Qt是最为出众、最受编程者的欢迎,所以我选择了它来制作我的GUI。

Qt制作GUI我在前面讲过,这里就不重复了。但是我不仅仅是把html网页嵌入到GUI里,我想做一个界面,一个可以直接看不止一个疫情地图的界面。这样就不仅仅是在Qt里拖动几个组件那么简单,而是需要再加入信号与槽。信号(Signal)就是一种通告,一种需要在特定情况下被发射(emit)的通告;而槽(Slot)则是对那些信号响应的函数。槽本质上就是一个函数,所以它就可以被调用。但是槽函数和其他函数不一样的地方是:槽函数是可以与其中一个信号相互关联,所以当发射某个信号那个刹那,与此相关联的对应槽函数会被自动执行。

别的话不多说了,我直接上图。在Qt里除非用到非常复杂的界面,不然只需简单操作即可获得一般界面。如下图4.16:

地图——基于python的gis开发与应用

 

图4.16 桌面疫情界面

这张图是一个显示2020年1月1日到10日疫情地图界面的截图。

这个方法的短板显露出来了。用这个界面不能放入超过10个HTML页面,不然界面会自动闪退,而且如果多次运行,电脑会直接黑屏。我上网查资料,发现这个现象被称为“堆栈溢出”,解决的办法涉及到多线程。我觉得好复杂,不如先设置一个总界面,上面有多个按钮,分别对应不同时间段,只是觉得这样做不美观就放弃了,我还是决定另辟蹊径。

 

 pytcharts的timeline

Timeline是时间线的意思。Pyecharts的时间线设定仿佛是为了我的需求而诞生的。我放一张pyecharts的tiemline示例图4.17和图4.18:

地图——基于python的gis开发与应用

 

图4.17 pyecharts的timeline1

地图——基于python的gis开发与应用

 

图4.18 pyecharts的timeline2

这个案例是关于中国每年各省GDP汇总。这个图例里不仅有地图和时间线,还有饼图、柱形图、折线图和时间线上的轮播(可自动播放)。

我根据这个案例修改为我需要的。如图4.19所示:

地图——基于python的gis开发与应用

 

图4.19 疫情地图四月份

这张图显示的是2020年4月份每一天疫情感染确诊人数情况图,其中包括GIS、折线图、柱形图和饼图,而且有数据显示。

虽然这个timeline非常好使,但是也有缺点。细数缺点:

A、里面的数据需要人工手动一个一个输入进去,目前我没有找到可以解决的办法。

B、目前我只能把一个月的数据进去,无法同时放五个月的。因此我为此做了五个不同的timeline。

C、这次做的地图跟之前做的不一样,之前那张可以在省的上方出现数据,而这张不行,数据是出现在另外一个小柱子上,有些不方便,但是目前我改动不了。

这个也可以简单地嵌入到PyQt5界面里,就不赘述了。

 

 PyInstaller打包

使用方法:

使用PyInstaller其实十分简单。打开命令提示符,把路径改到想要存储文件的地方(pyinstaller生成的文件与cmd起始位置息息相关,所以一定要选好路径),然后在cmd里敲入如下指令(举例,我这里用的源文件是pyecharts5.py):

>pyinstaller G:\pycharm\Spider\pyecharts5.py

在执行这条指令完成后,会在该文件夹下出现两个文件夹,分别为dist和build。其中:build是用来存储pyinstaller产生临时文件的目录(可安全删除);dist里面包含可执行文件pyecharts5.exe(可执行文件名同源文件名一样),其余文件是该可执行文件的动态链接库。

我点开pyecharts5.exe后先是出现如cmd类似的界面,而后才出现源文件编写的界面。如下图4.20所示:

地图——基于python的gis开发与应用

 

图4.20 打包后的桌面端界面

由于直接调用6.2里用到的.py文件,没有换别的文件,得到的结果同6.2的是一样的,只是输出方式不同,一个是pycharm输出,另一个是pyinstaller输出。

这个缺点就是运行太慢了。我等这个结果等了大概2到3分种(也有可能是源代码过于复杂的问题)。

Pyinstaller还有其它有用的用法,但是这里没用到,就不多做说明。