Python如何使用bokeh包和geojson数据绘制地图


Posted in Python onMarch 21, 2020

最近要绘制伦敦区地图,查阅了很多资料后最终选择使用bokeh包以及伦敦区的geojson数据绘制。
bokeh是基于python的绘图工具,可以绘制各种类型的图表,支持geojson数据的读取及绘制地图。

安装bokeh

$ pip install bokeh

软件版本

python-3.7.7bokeh-2.0.0

数据来源

伦敦地图数据来源于Highmaps地图数据集。下载的是英国的地图数据united-kindom.geo.json。需要对得到的数据进行预处理才能得到只含伦敦地区的数据。这需要对geojson数据的格式有一定的了解。在对数据进行处理之前,先看如何绘制英国地图。

绘制英国地图

from bokeh.plotting import curdoc, figure
from bokeh.models import GeoJSONDataSource

# 读入英国地图数据并传给GeoJSONDataSource
with open("united-kindom.geo.json", encoding="utf8") as f:
  geo_source = GeoJSONDataSource(geojson=f.read())
# 设置一张画布
p = figure(width=500, height=500)
# 使用patches函数以及geo_source绘制地图
p.patches(xs='xs', ys='ys', source=geo_source)

curdoc().add_root(p)

上述代码可以绘制出英国地图。将上述代码保存为test.py,在终端运行

$ bokeh serve --show test.py

这会自动打开浏览器,并显示英国地图。
运行结果如图:

Python如何使用bokeh包和geojson数据绘制地图

获取伦敦地区数据

获取伦敦地区数据可以手动从united-kingdom.geo.json文件中筛选出伦敦的数据,也可以先用python先把数据过滤一遍,然后将数据传给bokeh。这需要对geojson文件格式有一定的了解,在此不详细介绍。

from bokeh.plotting import curdoc, figure
from bokeh.models import GeoJSONDataSource
import json

# 用json库读取数据
with open("united-kindom.geo.json", encoding="utf8") as f:
  data = json.loads(f.read())
# 判断是不是伦敦地区数据
def isInLondon(district):
  if 'type' in district['properties'] and 'london borough' in district['properties']['type'].lower():
    return True
  if 'type-en' in district['properties'] and 'london borough' in district['properties']['type'].lower():
    return True
  if 'woe-name' in district['properties'] and 'city of london' in district['properties']['woe-name'].lower():
    return True
  return False
# 过滤数据
data['features'] = list(filter(isInLondon, data['features']))
#
geo_source = GeoJSONDataSource(geojson=json.dumps(data))
p = figure(width=500, height=500)
p.patches(xs='xs', ys='ys', source=geo_source)

curdoc().add_root(p)

运行结果如图:

Python如何使用bokeh包和geojson数据绘制地图

美化

上面的伦敦地图只是一个大概的轮廓,下面对地图添加一系列功能。

添加各区轮廓线

p.patches(xs='xs', ys='ys', fill_alpha=0.7, # 画轮廓线
    line_color='white', # 线的颜色
    line_width=0.5,   # 线的宽度
    source=geo_source)

现在地图区域轮廓很清晰。

添加颜色

# 为每一个地区增加一个color属性
for i in range(len(data['features'])):
  data['features'][i]['properties']['color'] = ['blue', 'red', 'yellow', 'orange', 'gray', 'purple'][i % 6]
p.patches(xs='xs', ys='ys', fill_alpha=0.7,
    line_color='white',
    line_width=0.5,
    color="color",  # 增加颜色属性,这里的"color"对应每个地区的color属性
    source=geo_source)

现在地图五颜六色。

增加图注

import random
# 随机产生数据用于展示
for i in range(len(data['features'])):
  data['features'][i]['properties']['number'] = random.randint(0, 20_000)
p = figure(width=500, height=500,
    tooltips="@name, number: @number" # 使用tooltips生成图注,@+属性名称,这里的name是数据中原本有的,number是新近添加的。
  )

现在鼠标放到区域上时,会显示"区域名, number: 数字"。

去掉坐标轴与背景线

p.axis.axis_label = None
p.axis.visible = False
p.grid.grid_line_color = None

最终代码

from bokeh.plotting import curdoc, figure
from bokeh.models import GeoJSONDataSource
import json
import random
with open("united-kindom.geo.json", encoding="utf8") as f:
  data = json.loads(f.read())

def isInLondon(district):
  if 'type' in district['properties'] and 'london borough' in district['properties']['type'].lower():
    return True
  if 'type-en' in district['properties'] and 'london borough' in district['properties']['type'].lower():
    return True
  if 'woe-name' in district['properties'] and 'city of london' in district['properties']['woe-name'].lower():
    return True
  return False

data['features'] = list(filter(isInLondon, data['features']))
for i in range(len(data['features'])):
  data['features'][i]['properties']['color'] = ['blue', 'red', 'yellow', 'orange', 'gray', 'purple'][i % 6]
  data['features'][i]['properties']['number'] = random.randint(0, 20_000)

geo_source = GeoJSONDataSource(geojson=json.dumps(data))
p = figure(width=500, height=500,
    tooltips="@name, number: @number")
p.patches(xs='xs', ys='ys', fill_alpha=0.7,
    line_color='white',
    line_width=0.5,
    color="color",
    source=geo_source)

p.axis.axis_label = None
p.axis.visible = False
p.grid.grid_line_color = None

curdoc().add_root(p)

伦敦地图完成了

Python如何使用bokeh包和geojson数据绘制地图

总结

最开始想用pyecharts做的,但是pyecharts并没有伦敦的地图。折腾半天,最后只好自己找geojson数据来画地图。

找到了很多关于地图的数据和工具,比如上文中提到的highmap数据集,以及DataV.altas,这个工具可以可视化地提取中国区域的地图数据,但感觉比起自己找数据,画中国地图还是pyecharts来得实在。

数据最重要。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用cx_freeze把python打包exe示例
Jan 24 Python
python在windows和linux下获得本机本地ip地址方法小结
Mar 20 Python
对Python3中的input函数详解
Apr 22 Python
pandas进行数据的交集与并集方式的数据合并方法
Jun 27 Python
python中join()方法介绍
Oct 11 Python
python3人脸识别的两种方法
Apr 25 Python
解决python中用matplotlib画多幅图时出现图形部分重叠的问题
Jul 07 Python
python匿名函数lambda原理及实例解析
Feb 07 Python
python GUI库图形界面开发之PyQt5打印控件QPrinter详细使用方法与实例
Feb 28 Python
解决使用python print打印函数返回值多一个None的问题
Apr 09 Python
python利用os模块编写文件复制功能——copy()函数用法
Jul 13 Python
python pip如何手动安装二进制包
Sep 30 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
Mar 20 #Python
python+opencv实现移动侦测(帧差法)
Mar 20 #Python
Java Spring项目国际化(i18n)详细方法与实例
Mar 20 #Python
Python 自由定制表格的实现示例
Mar 20 #Python
python实现opencv+scoket网络实时图传
Mar 20 #Python
python实现同一局域网下传输图片
Mar 20 #Python
python实现udp传输图片功能
Mar 20 #Python
You might like
php录入页面中动态从数据库中提取数据的实现
2006/10/09 PHP
php读取javascript设置的cookies的代码
2010/04/12 PHP
php图片加水印原理(超简单的实例代码)
2013/01/18 PHP
php连接函数implode与分割explode的深入解析
2013/06/26 PHP
深入理解PHP原理之执行周期分析
2016/06/01 PHP
PHP命令行执行整合pathinfo模拟定时任务实例
2016/08/12 PHP
javascript 动态添加事件代码
2008/11/30 Javascript
jQuery EasyUI API 中文文档 - NumberSpinner数值微调器使用介绍
2011/10/21 Javascript
Javascript面向对象编程
2012/03/18 Javascript
JS正则表达式大全(整理详细且实用)
2013/11/14 Javascript
JQuery 在线引用及测试引用是否成功
2014/06/24 Javascript
jQuery实现滚动鼠标放大缩小图片的方法(附demo源码下载)
2016/03/05 Javascript
JavaScript编程中实现对象封装特性的实例讲解
2016/06/24 Javascript
解决在vue+webpack开发中出现两个或多个菜单公用一个组件问题
2017/11/28 Javascript
详解Nuxt.js Vue服务端渲染摸索
2018/02/08 Javascript
jQuery无冲突模式详解
2019/01/17 jQuery
babel7.x和webpack4.x配置vue项目的方法步骤
2019/05/12 Javascript
vue elementUI 表单校验功能之数组多层嵌套
2019/06/04 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
vue 实现tab切换保持数据状态
2020/07/21 Javascript
使用Python中的tkinter模块作图的方法
2017/02/07 Python
Python学习之Django的管理界面代码示例
2018/02/10 Python
对python中的高效迭代器函数详解
2018/10/18 Python
使用Python给头像加上圣诞帽或圣诞老人小图标附源码
2019/12/25 Python
Tensorflow: 从checkpoint文件中读取tensor方式
2020/02/10 Python
Django单元测试中Fixtures的使用方法
2020/02/26 Python
用 Python 制作地球仪的方法
2020/04/24 Python
将不规则的Python多维数组拉平到一维的方法实现
2021/01/11 Python
大学生旷课检讨书
2014/01/22 职场文书
幼儿园消防演练方案
2014/02/13 职场文书
教师自我反思材料
2014/02/14 职场文书
小学生迎国庆演讲稿
2014/09/05 职场文书
部门2014年度工作总结
2014/11/12 职场文书
领导干部失职检讨书
2015/05/05 职场文书
祝寿主持词
2015/07/02 职场文书
学习十八大的感悟
2015/08/11 职场文书