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 yield 使用浅析
May 28 Python
十条建议帮你提高Python编程效率
Feb 16 Python
python实现Excel文件转换为TXT文件
Apr 28 Python
python常用库之NumPy和sklearn入门
Jul 11 Python
解决python中导入win32com.client出错的问题
Jul 26 Python
pandas DataFrame的修改方法(值、列、索引)
Aug 02 Python
Python数据可视化:饼状图的实例讲解
Dec 07 Python
pytorch实现从本地加载 .pth 格式模型
Feb 14 Python
Python多线程thread及模块使用实例
Apr 28 Python
Python实现ElGamal加密算法的示例代码
Jun 19 Python
哪种Python框架适合你?简单介绍几种主流Python框架
Aug 04 Python
Python 匹配文本并在其上一行追加文本
May 11 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 编程安全性小结
2010/01/08 PHP
使用dump函数,给php加断点测试
2013/06/25 PHP
Codeigniter上传图片出现“You did not select a file to upload”错误解决办法
2014/06/12 PHP
ThinkPHP框架实现的邮箱激活功能示例
2018/06/15 PHP
JavaScript 开发中规范性的一点感想
2009/06/23 Javascript
JavaScript中string转换成number介绍
2014/12/31 Javascript
充分发挥Node.js程序性能的一些方法介绍
2015/06/23 Javascript
JS实现的Select三级下拉菜单代码
2015/08/20 Javascript
AngularJS中transclude用法详解
2016/11/03 Javascript
JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法
2017/04/28 Javascript
js基于FileSaver.js 浏览器导出Excel文件的示例
2017/08/15 Javascript
JS点击图片弹出文件选择框并覆盖原图功能的实现代码
2017/08/25 Javascript
vuex与组件联合使用的方法
2018/05/10 Javascript
webpack配置proxyTable时pathRewrite无效的解决方法
2018/12/13 Javascript
vue ssr 实现方式(学习笔记)
2019/01/18 Javascript
js实现图片3D轮播效果
2019/09/21 Javascript
JavaScript setTimeout()基本用法有哪些
2020/11/04 Javascript
[01:24:51]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS NewBee第二场
2014/05/26 DOTA
[01:32:22]DOTA2-DPC中国联赛 正赛 Ehome vs VG BO3 第一场 2月5日
2021/03/11 DOTA
Python基于PycURL实现POST的方法
2015/07/25 Python
Python流行ORM框架sqlalchemy安装与使用教程
2019/06/04 Python
python字符串替换第一个字符串的方法
2019/06/26 Python
Pycharm导入anaconda环境的教程图解
2020/07/31 Python
python 通过 pybind11 使用Eigen加速代码的步骤
2020/12/07 Python
html5简单示例_动力节点Java学院整理
2017/07/07 HTML / CSS
JD Sports芬兰:英国领先的运动鞋和运动服饰零售商
2018/11/16 全球购物
美国亚洲时尚和美容产品的一站式网上商店:Stylevana
2019/09/05 全球购物
大学生表扬信范文
2014/01/09 职场文书
电子商务专业学生职业生涯规划
2014/03/07 职场文书
电子装配专业毕业生求职信
2014/04/23 职场文书
团日活动总结书格式
2014/05/08 职场文书
会计出纳岗位职责
2015/03/31 职场文书
行政助理岗位职责范本
2015/04/11 职场文书
广播体操比赛主持词
2015/06/29 职场文书
Python OpenCV实现传统图片格式与base64转换
2021/06/13 Python
厉害!这是Redis可视化工具最全的横向评测
2021/07/15 Redis