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 相关文章推荐
学习python (2)
Oct 31 Python
python中的一些类型转换函数小结
Feb 10 Python
使用python提取html文件中的特定数据的实现代码
Mar 24 Python
Python获取运行目录与当前脚本目录的方法
Jun 01 Python
Python数据分析中Groupby用法之通过字典或Series进行分组的实例
Dec 08 Python
python机器学习之神经网络(二)
Dec 20 Python
强悍的Python读取大文件的解决方案
Feb 16 Python
python三引号输出方法
Feb 27 Python
浅谈Python3实现两个矩形的交并比(IoU)
Jan 18 Python
python 给图像添加透明度(alpha通道)
Apr 09 Python
jupyter notebook运行命令显示[*](解决办法)
May 18 Python
python 实现"神经衰弱"翻牌游戏
Nov 09 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
BBS(php & mysql)完整版(二)
2006/10/09 PHP
相对路径转化成绝对路径
2007/04/10 PHP
请php正则走开
2008/03/15 PHP
php smarty的预保留变量总结
2008/12/04 PHP
PHP 文件系统详解
2012/09/13 PHP
javascript-简单的计算器实现步骤分解(附图)
2013/05/30 Javascript
JS小功能(列表页面隔行变色)简单实现
2013/11/28 Javascript
JavaScript中的acos()方法使用详解
2015/06/14 Javascript
jQuery 3.0 的变化及使用方法
2016/02/01 Javascript
jQuery实现图片局部放大镜效果
2016/03/17 Javascript
使用JavaScript为Kindeditor自定义按钮增加Audio标签
2016/03/18 Javascript
js本地图片预览实现代码
2016/10/09 Javascript
vuejs父子组件通信的问题
2017/01/11 Javascript
微信小程序 连续旋转动画(this.animation.rotate)详解
2017/04/07 Javascript
JS实现给json数组动态赋值的方法示例
2020/03/19 Javascript
React Native中的RefreshContorl下拉刷新使用
2017/10/09 Javascript
纯js实现隔行变色效果
2017/11/29 Javascript
npm 下载指定版本的组件方法
2018/05/17 Javascript
关于python的bottle框架跨域请求报错问题的处理方法
2017/03/19 Python
用python生成1000个txt文件的方法
2018/10/25 Python
python使用MQTT给硬件传输图片的实现方法
2019/05/05 Python
Python学习笔记之自定义函数用法详解
2019/06/08 Python
python构造IP报文实例
2020/05/05 Python
Python 中如何使用 virtualenv 管理虚拟环境
2021/01/21 Python
介绍一下Make? 为什么使用make
2016/07/31 面试题
《云雀的心愿》教学反思
2014/02/25 职场文书
二手房买卖协议书
2014/04/10 职场文书
党员个人公开承诺书
2014/08/29 职场文书
自我推荐信怎么写
2015/03/24 职场文书
终止解除劳动合同证明书
2015/06/17 职场文书
国际贸易实训总结
2015/08/03 职场文书
一年级下册数学教学反思
2016/02/16 职场文书
解决thinkphp6(tp6)在状态码500下不报错,或者显示错误“Malformed UTF-8 characters”的问题
2021/04/01 PHP
nginx实现动静分离的方法示例
2021/11/07 Servers
深入解读Java三大集合之map list set的用法
2021/11/11 Java/Android
攻略丨滑雪究竟该选哪款对讲机?
2022/02/18 无线电