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中用于转换字母为小写的lower()方法使用简介
May 19 Python
python中pandas.DataFrame对行与列求和及添加新行与列示例
Mar 12 Python
Python使用matplotlib填充图形指定区域代码示例
Jan 16 Python
Tornado Web Server框架编写简易Python服务器
Jul 28 Python
python 读取摄像头数据并保存的实例
Aug 03 Python
python安装twisted的问题解析
Aug 21 Python
python将txt文件读取为字典的示例
Dec 22 Python
python mysql断开重连的实现方法
Jul 26 Python
Python解决pip install时出现的Could not fetch URL问题
Aug 01 Python
python简单利用字典破解zip文件口令
Sep 07 Python
如何创建一个Flask项目并进行简单配置
Nov 18 Python
python中pop()函数的语法与实例
Dec 01 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
S900/ ETON E1-XM 收音机
2021/03/02 无线电
黑夜路人出的几道php笔试题
2009/08/04 PHP
php获得url参数中具有&的值的方法
2014/03/05 PHP
php+ajax导入大数据时产生的问题处理
2014/06/11 PHP
php传值赋值和传地址赋值用法实例分析
2015/06/20 PHP
浅析ThinkPHP缓存之快速缓存(F方法)和动态缓存(S方法)(日常整理)
2015/10/26 PHP
yii2学习教程之5种内置行为类详解
2017/08/03 PHP
JavaScript 提升运行速度之循环篇 译文
2009/08/15 Javascript
JS获取dom 对象 ajax操作 读写cookie函数
2009/11/18 Javascript
JavaScript 面向对象的之私有成员和公开成员
2010/05/04 Javascript
style、 currentStyle、 runtimeStyle区别分析
2010/08/01 Javascript
理解Javascript_13_执行模型详解
2010/10/20 Javascript
jquery刷新页面的实现代码(局部及全页面刷新)
2011/07/11 Javascript
基于jQuery的星级评分插件
2011/08/12 Javascript
jquery.messager.js插件导致页面抖动的解决方法
2013/07/14 Javascript
express的中间件bodyParser详解
2014/12/04 Javascript
JS实现双击屏幕滚动效果代码
2015/10/28 Javascript
Extjs4.0 ComboBox如何实现三级联动
2016/05/11 Javascript
AngularJS框架中的双向数据绑定机制详解【减少需要重复的开发代码量】
2017/01/19 Javascript
微信小程序-滚动消息通知的实例代码
2017/08/03 Javascript
JavaScript遍历数组的三种方法map、forEach与filter实例详解
2019/02/27 Javascript
Js参数RSA加密传输之jsencrypt.js的使用
2020/02/07 Javascript
在Python的web框架中配置app的教程
2015/04/30 Python
详解Python中的序列化与反序列化的使用
2015/06/30 Python
Python 数据结构之堆栈实例代码
2017/01/22 Python
Windows安装Python、pip、easy_install的方法
2017/03/05 Python
用python 批量更改图像尺寸到统一大小的方法
2018/03/31 Python
jenkins配置python脚本定时任务过程图解
2019/10/29 Python
Python基于字典实现switch case函数调用
2020/07/22 Python
美国老牌主机服务商:iPage
2016/07/22 全球购物
联想新西兰官方网站:Lenovo New Zealand
2018/10/30 全球购物
导游个人求职信范文
2014/03/23 职场文书
关于教师节的演讲稿
2014/09/04 职场文书
2015年英语教师工作总结
2015/05/20 职场文书
利用Selenium添加cookie实现自动登录的示例代码(fofa)
2021/05/08 Python
Redis中一个String类型引发的惨案
2021/07/25 Redis