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的Flask框架与数据库连接的教程
Apr 20 Python
在阿里云服务器上配置CentOS+Nginx+Python+Flask环境
Jun 18 Python
python中Apriori算法实现讲解
Dec 10 Python
python实现微信小程序自动回复
Sep 10 Python
对json字符串与python字符串的不同之处详解
Dec 19 Python
这可能是最好玩的python GUI入门实例(推荐)
Jul 19 Python
Django使用unittest模块进行单元测试过程解析
Aug 02 Python
Python基于Tensor FLow的图像处理操作详解
Jan 15 Python
Python实现的北京积分落户数据分析示例
Mar 27 Python
Python Selenium截图功能实现代码
Apr 26 Python
Django多层嵌套ManyToMany字段ORM操作详解
May 19 Python
Python字符串格式化方式
Apr 07 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 cookie 登录验证示例代码
2009/03/16 PHP
php join函数应用
2011/05/04 PHP
PHP常用正则表达式集锦
2014/08/17 PHP
PHP计算百度地图两个GPS坐标之间距离的方法
2015/01/09 PHP
JQuery以JSON方式提交数据到服务端示例代码
2014/05/05 Javascript
jquery 页眉单行信息滚动显示实现思路及代码
2014/06/26 Javascript
IE8中动态创建script标签onload无效的解决方法
2014/12/22 Javascript
js密码强度检测
2016/01/07 Javascript
Function.prototype.apply()与Function.prototype.call()小结
2016/04/27 Javascript
bootstrap datetimepicker日期插件超详细使用方法介绍
2017/02/23 Javascript
利用pm2部署多个node.js项目的配置教程
2017/10/22 Javascript
用React实现一个完整的TodoList的示例代码
2017/10/30 Javascript
vue 添加vux的代码讲解
2017/11/30 Javascript
three.js 入门案例详解
2018/01/23 Javascript
在react-router4中进行代码拆分的方法(基于webpack)
2018/03/08 Javascript
layui实现文件或图片上传记录
2018/08/28 Javascript
微信小程序中target和currentTarget的区别小结
2020/11/06 Javascript
[08:47]2018国际邀请赛 OG战队举杯时刻
2018/08/29 DOTA
Python函数中*args和**kwargs来传递变长参数的用法
2016/01/26 Python
Python使用numpy模块创建数组操作示例
2018/06/20 Python
python实现音乐播放器 python实现花框音乐盒子
2020/02/25 Python
Python设计密码强度校验程序
2020/07/30 Python
幼儿教师国培感言
2014/02/19 职场文书
公司年会策划方案
2014/05/17 职场文书
团日活动总结怎么写
2014/06/25 职场文书
学校四风问题对照检查材料思想汇报
2014/09/26 职场文书
2014年学生会部门工作总结
2014/11/07 职场文书
标准离婚协议书范文下载
2014/11/30 职场文书
2015年毕业实习工作总结
2014/12/12 职场文书
出纳试用期自我评价
2015/03/10 职场文书
导游词之平津战役纪念馆
2019/11/04 职场文书
为什么不建议在go项目中使用init()
2021/04/12 Golang
CSS3实现的文字弹出特效
2021/04/16 HTML / CSS
python中subplot大小的设置步骤
2021/06/28 Python
SQLServer RANK() 排名函数的使用
2022/03/23 SQL Server
volatile保证可见性及重排序方法
2022/08/05 Java/Android