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使用urllib2模块获取gravatar头像实例
Dec 18 Python
Python3.x中自定义比较函数
Apr 24 Python
用Python程序抓取网页的HTML信息的一个小实例
May 02 Python
Python实现HTTP协议下的文件下载方法总结
Apr 20 Python
浅析Python 中整型对象存储的位置
May 16 Python
Python从ZabbixAPI获取信息及实现Zabbix-API 监控的方法
Sep 17 Python
Python使用googletrans报错的解决方法
Sep 25 Python
python使用udp实现聊天器功能
Dec 10 Python
python实现桌面气泡提示功能
Jul 29 Python
Flask框架学习笔记之消息提示与异常处理操作详解
Aug 15 Python
Python 数据可视化之Seaborn详解
Nov 02 Python
Python爬虫 简单介绍一下Xpath及使用
Apr 26 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中接口与抽象类的区别
2013/06/08 PHP
php实现连接access数据库并转txt写入的方法
2017/02/08 PHP
基于jQuery的图片大小自动适应实现代码
2010/11/17 Javascript
jQuery实现自定义事件的方法
2015/04/17 Javascript
js实现的后台左侧管理菜单代码
2015/09/11 Javascript
MVC+jQuery.Ajax异步实现增删改查和分页
2020/12/22 Javascript
js实现为a标签添加事件的方法(使用闭包循环)
2016/08/02 Javascript
node.js 利用流实现读写同步,边读边写的方法
2017/09/11 Javascript
JavaScript引用类型Object常见用法实例分析
2018/08/08 Javascript
深入了解js原型模式
2019/05/30 Javascript
详解Vue 单文件组件的三种写法
2020/02/19 Javascript
利用JavaScript模拟京东按键输入功能
2020/12/01 Javascript
element el-table表格的二次封装实现(附表格高度自适应)
2021/01/19 Javascript
[02:20]DOTA2亚洲邀请赛 IG战队出场宣传片
2015/02/07 DOTA
仅利用30行Python代码来展示X算法
2015/04/01 Python
Python的ORM框架中SQLAlchemy库的查询操作的教程
2015/04/25 Python
对Tensorflow中权值和feature map的可视化详解
2018/06/14 Python
详解安装mitmproxy以及遇到的坑和简单用法
2019/01/21 Python
Python魔法方法 容器部方法详解
2020/01/02 Python
Python通过2种方法输出带颜色字体
2020/03/02 Python
通过实例解析Python RPC实现原理及方法
2020/07/07 Python
python安装cx_Oracle和wxPython的方法
2020/09/14 Python
使用Python实现音频双通道分离
2020/12/25 Python
html5实现的便签特效(实战分享)
2013/11/29 HTML / CSS
英国手机零售商:Carphone Warehouse
2018/06/06 全球购物
数据库基础的一些面试题
2012/02/25 面试题
国贸专业求职信
2014/06/28 职场文书
研究生导师评语
2014/12/31 职场文书
表扬稿范文
2015/01/17 职场文书
难以忽视的真相观后感
2015/06/05 职场文书
运动会200米广播稿
2015/08/19 职场文书
为什么阅读对所有年龄段的孩子都很重要?
2019/07/08 职场文书
话题作文之呼唤
2019/12/18 职场文书
golang中的空slice案例
2021/04/27 Golang
Redis中缓存穿透/击穿/雪崩问题和解决方法
2021/12/04 Redis
工厂无线对讲系统解决方案
2022/02/18 无线电