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 相关文章推荐
Django中的CACHE_BACKEND参数和站点级Cache设置
Jul 23 Python
Python编程判断这天是这一年第几天的方法示例
Apr 18 Python
学习Python3 Dlib19.7进行人脸面部识别
Jan 24 Python
tensorflow中next_batch的具体使用
Feb 02 Python
使用python获取电脑的磁盘信息方法
Nov 01 Python
解决python xlrd无法读取excel文件的问题
Dec 25 Python
图文详解python安装Scrapy框架步骤
May 20 Python
python查看文件大小和文件夹内容的方法
Jul 08 Python
使用python 的matplotlib 画轨道实例
Jan 19 Python
python序列类型种类详解
Feb 26 Python
完美解决keras保存好的model不能成功加载问题
Jun 11 Python
pycharm激活码2020最新分享适用pycharm2020最新版亲测可用
Nov 22 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
谈一谈收音机的高放电路
2021/03/02 无线电
PHP使用静态方法的几个注意事项
2014/09/16 PHP
PHP 下载文件时如何自动添加bom头及解释BOM头和去掉bom头的方法
2016/01/04 PHP
php 二维数组时间排序实现代码
2016/11/19 PHP
PHP删除二维数组中相同元素及数组重复值的方法示例
2017/05/05 PHP
php 使用expat方式解析xml文件操作示例
2019/11/26 PHP
JavaScript语言中的Literal Syntax特性分析
2007/03/08 Javascript
javascript的函数作用域
2014/11/12 Javascript
jQuery实现行文字链接提示效果的方法
2015/03/10 Javascript
javascript封装的sqlite操作类实例
2015/07/17 Javascript
一分钟理解js闭包
2016/05/04 Javascript
Vue监听数组变化源码解析
2017/03/09 Javascript
基于DOM节点删除之empty和remove的区别(详解)
2017/09/11 Javascript
node.js学习笔记之koa框架和简单爬虫练习
2018/12/13 Javascript
vue+iview动态渲染表格详解
2019/03/19 Javascript
Vue插件之滑动验证码
2019/09/21 Javascript
Python中用于检查英文字母大写的isupper()方法
2015/05/19 Python
网易2016研发工程师编程题 奖学金(python)
2019/06/19 Python
谈一谈数组拼接tf.concat()和np.concatenate()的区别
2020/02/07 Python
Python偏函数Partial function使用方法实例详解
2020/06/17 Python
Matplotlib自定义坐标轴刻度的实现示例
2020/06/18 Python
Python pip使用超时问题解决方案
2020/08/03 Python
解锁canvas导出图片跨域的N种姿势小结
2019/01/24 HTML / CSS
KIKO MILANO西班牙官网:意大利领先的化妆品和护肤品品牌
2019/05/03 全球购物
如何利用XMLHTTP检测URL及探测服务器信息
2013/11/10 面试题
销售简历自我评价
2014/01/24 职场文书
班组安全员工作职责
2014/02/01 职场文书
《生命 生命》教学反思
2014/04/19 职场文书
机械制造专业大学生自我鉴定
2014/09/19 职场文书
钱塘江大潮导游词
2015/02/03 职场文书
2015年社区工作总结
2015/04/08 职场文书
行政经理岗位职责
2015/04/15 职场文书
无犯罪记录证明样本
2015/06/16 职场文书
公开致歉信
2019/06/24 职场文书
导游词之无锡华莱坞
2019/12/02 职场文书
Python基础之函数嵌套知识总结
2021/05/23 Python