利用Python实现Shp格式向GeoJSON的转换方法


Posted in Python onJuly 09, 2019

一、简介

Shp格式是GIS中非常重要的数据格式,主要在Arcgis中使用,但在进行很多基于网页的空间数据可视化时,通常只接受GeoJSON格式的数据,众所周知JSON(JavaScript Object Nonation)是利用键值对+嵌套来表示数据的一种格式,以其轻量、易解析的优点,被广泛使用与各种领域,而GeoJSON就是指在一套规定的语法规则下用JSON格式存储矢量数据,本文就将针对GeoJSON的语法规则,以及如何利用Python完成Shp格式到GeoJSON格式的转换进行介绍。

二、Shp转GeoJSON

2.1 GeoJSON格式说明

GeoJSON本质依旧是JSON,其基本格式如下:

{
 "type": "FeatureCollection",
 "features": []
}

一个完整的GeoJSON文件最外层为一个字典,把整个GeoJSON文件看做自顶向下的树状结构的话,其根目录包含键值对 "type":"FeaturesCollection" ,以及存放所有要素的键值对 "features":[] ,所有矢量要素都存放在这个列表中,每个要素都是一个字典,下面我们来认识一下各种矢量要素在GeoJSON中的规范格式:

点要素(Point):

对于单个点要素,其格式如下:

{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"Point",
  "coordinates":[经度,纬度]
  }
 }

其中properties对应的值为这个要素对应的属性表中按顺序存放的值,geometry对应的值中type指明了要素类型,coordinates传入一个包含两个元素的列表,第一个元素代表经度,第二个元素代表纬度。

多点要素(MultiPoint):

多点要素是点要素的特殊情况,其geometry下的type属性传入"MultiPoint",其coordinates属性传入的是一个二维列表,其最内层列表定义了每个点的经纬度,如下:

{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"MultiPoint",
  "coordinates":[[经度1,纬度1],
    [经度2,纬度2]
   ]
  }
  }

线要素(LineString):

线要素记录的是一条线上所有折点的经纬度信息,只需要按顺序连接这些折点就可以还原一条线的形态,在GeoJSON中线要素与多点要素在coordinates属性上格式相同,区别在于geometry属性需要传入"LineString",如下:

{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"LineString",
  "coordinates":[[经度1,纬度1],
  [经度2,纬度2],
  [经度3,纬度3],
  [经度4,,纬度4]]
  }
 }

多线要素(MultiLineString):

多线要素是多个线要素的组合,因此其coordinates传入三维列表,来组合多条线,对应的geometry下type属性为"MultiLineString",如下:

{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"MultiLineString",
  "coordinates":
  [
   [
    [经度1,纬度1],
    [经度2,纬度2],
    [经度3,纬度3],
    [经度4,纬度4]
   ],
   [
    [经度5,纬度5],
    [经度6,纬度6]
   ]
  ]
    }
 }

多边形要素(Polygon):

多边形要素记录了构成一个多边形所有边缘折点的经纬度信息,其coordinates属性传入"Polygon",其geometry下type属性格式为三维列表,其第三层列表中嵌套的所有列表记录的经纬度按顺序连接即构成了一个多边形,但需要注意的是,多边形头尾折点的经纬度需要相同,才能构成一个闭合的多边形,如下:

{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"Polygon",
  "coordinates":[
      [
       [经度1,纬度1],
       [经度2,纬度2],
       [经度3,纬度3],
       [经度4,纬度4],
       [经度1,纬度1]
      ]
      ]
  }
 }

多多边形要素(MultiPolygon):

多多边形的格式为四维列表,其geometry下type属性传入"MultiPloygon",由于多多边形要素中存在几种特殊情况,下面我们在geojson.io中进行对应GeoJSON数据的可视化以便于理解:

互不重叠的两个多边形:

下面是互不重叠的两个多边形的示例: 

利用Python实现Shp格式向GeoJSON的转换方法

对应的GeoJSON数据如下:

{
 "type": "Feature",
 "properties": {},
 "geometry": {
 "type": "MultiPolygon",
 "coordinates":
 [ 
  [
   [
    [102.74414062499999,36.217687122250574],
    [102.7001953125,35.585851593232356],
    [104.8590087890625,35.496456056584165],
    [104.96337890625,36.24427318493909],
    [102.74414062499999,36.217687122250574]
   ]
  ],
  [
   [
    [102.6397705078125,35.074964853989556],
    [103.0352783203125,34.23905366851639],
    [105.00732421875,34.24813554589752],
    [105.3973388671875,35.77771427205079],
    [104.556884765625,35.05698043137265],
    [102.711181640625,35.16931803601131],
    [102.6397705078125,35.074964853989556]
   ]
  ]
 ]
    }
}

可以看到在多个多边形不重叠时,直接将两个多边形要素对应的三维列表存放在最外层列表下即可。

互有重叠的两个多边形:

互有重叠的多个多边形要素格式同多个不重叠的多边形,效果如下:

 利用Python实现Shp格式向GeoJSON的转换方法

对应的GeoJSON数据如下:

{
 "type": "Feature",
 "properties": {},
 "geometry": {
 "type": "MultiPolygon",
 "coordinates": [
  [
  [
   [101.6455078125,27.68352808378776],
   [114.78515624999999,27.68352808378776],
   [114.78515624999999, 35.209721645221386],
   [101.6455078125,35.209721645221386],
   [101.6455078125,27.68352808378776]
  ]
  ],
  [
  [
   [104.2822265625,30.107117887092357],
   [108.896484375,30.107117887092357],
   [108.896484375,33.76088200086917],
   [104.2822265625,33.76088200086917],
   [104.2822265625,30.107117887092357]
  ]
  ]
 ]
 }
}

有孔的多边形:

有孔的多边形在类别上也是归类到MultiPolygon,下面是一个示例:

 利用Python实现Shp格式向GeoJSON的转换方法

对应的GeoJSON数据如下,可以看出其与多个重叠的多边形的区别在于多边形矢量信息嵌套在第二层列表中:

{
  "type": "Feature",
  "properties": {},
  "geometry": {
  "type": "MultiPolygon",
  "coordinates":
 [ 
  [
   [
    [101.6455078125,27.68352808378776],
    [114.78515624999999,27.68352808378776],
    [114.78515624999999,35.209721645221386],
    [101.6455078125,35.209721645221386],
    [101.6455078125,27.68352808378776]
   ],
   [
    [104.2822265625,30.107117887092357],
    [108.896484375,30.107117887092357],
    [108.896484375,33.76088200086917],
    [104.2822265625,33.76088200086917],
    [104.2822265625,30.107117887092357]
   ]
  ]
 ]
 }
}

2.2 将Shp格式转换为GeoJSON

在2.1中我们较为详细的了解到矢量数据在GeoJSON数据中具体的表现形式,通过下面的自编函数,以Shp文件名称(去除文件拓展名)、Shp文件编码、GeoJSON文件编码为输入参数:

def Shp2JSON(filename,shp_encoding='utf-8',json_encoding='utf-8'):
 '''
 这个函数用于将shp文件转换为GeoJSON文件
 :param filename: shp文件对应的文件名(去除文件拓展名)
 :return:
 '''

 '''创建shp IO连接'''
 reader = shapefile.Reader(filename,encoding=shp_encoding)

 '''提取所有field部分内容'''
 fields = reader.fields[1:]

 '''提取所有field的名称'''
 field_names = [field[0] for field in fields]

 '''初始化要素列表'''
 buffer = []

 for sr in tqdm(reader.shapeRecords()):
  '''提取每一个矢量对象对应的属性值'''
  record = sr.record

  '''属性转换为列表'''
  record = [r.decode('gb2312','ignore') if isinstance(r, bytes)
     else r for r in record]

  '''对齐属性与对应数值的键值对'''
  atr = dict(zip(field_names, record))

  '''获取当前矢量对象的类型及矢量信息'''
  geom = sr.shape.__geo_interface__

  '''向要素列表追加新对象'''
  buffer.append(dict(type="Feature",
       geometry=geom,
       properties=atr))

 '''写出GeoJSON文件'''
 geojson = codecs.open(filename + "-geo.json","w", encoding=json_encoding)
 geojson.write(json.dumps({"type":"FeatureCollection",
        "features":buffer}) + '\n')
 geojson.close()
 print('转换成功!')

下面我们通过一个示例来展示实际转换效果,使用到的Shp数据为中国省份数据,在arcgis中效果如下:

 利用Python实现Shp格式向GeoJSON的转换方法

import shapefile
import json
import codecs

def Shp2JSON(filename,shp_encoding='utf-8',json_encoding='utf-8'):
 '''
 这个函数用于将shp文件转换为GeoJSON文件
 :param filename: shp文件对应的文件名(去除文件拓展名)
 :return:
 '''

 '''创建shp IO连接'''
 reader = shapefile.Reader(filename,encoding=shp_encoding)

 '''提取所有field部分内容'''
 fields = reader.fields[1:]

 '''提取所有field的名称'''
 field_names = [field[0] for field in fields]

 '''初始化要素列表'''
 buffer = []

 for sr in tqdm(reader.shapeRecords()):
  '''提取每一个矢量对象对应的属性值'''
  record = sr.record

  '''属性转换为列表'''
  record = [r.decode('gb2312','ignore') if isinstance(r, bytes)
     else r for r in record]

  '''对齐属性与对应数值的键值对'''
  atr = dict(zip(field_names, record))

  '''获取当前矢量对象的类型及矢量信息'''
  geom = sr.shape.__geo_interface__

  '''向要素列表追加新对象'''
  buffer.append(dict(type="Feature",
       geometry=geom,
       properties=atr))

 '''写出GeoJSON文件'''
 geojson = codecs.open(filename + "-geo.json","w", encoding=json_encoding)
 geojson.write(json.dumps({"type":"FeatureCollection",
        "features":buffer}) + '\n')
 geojson.close()
 print('转换成功!')


if __name__ == '__main__':
 import os
 os.chdir(r'C:\Users\hp\Desktop\飞线图素材')
 Shp2JSON(filename='bou2_4p.shp',
    shp_encoding='gbk',
    json_encoding='utf-8')

运行之后同一目录下出现对应的json文件:

 利用Python实现Shp格式向GeoJSON的转换方法

导入到Kepler.gl中进行可视化:

from keplergl import KeplerGl
import json
with open('bou2_4p.shp-geo.json') as b:
 data = json.load(b)
map1 = KeplerGl(height=700,data={'layer1':data});map1

利用Python实现Shp格式向GeoJSON的转换方法

总结

以上所述是小编给大家介绍的利用Python实现Shp格式向GeoJSON的转换方法 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
python网络编程学习笔记(二):socket建立网络客户端
Jun 09 Python
Python采集腾讯新闻实例
Jul 10 Python
Linux下Python获取IP地址的代码
Nov 30 Python
详解 Python 与文件对象共事的实例
Sep 11 Python
Python自动化运维_文件内容差异对比分析
Dec 13 Python
pyQt4实现俄罗斯方块游戏
Jun 26 Python
python挖矿算力测试程序详解
Jul 03 Python
如何用Python来搭建一个简单的推荐系统
Aug 07 Python
Django自定义全局403、404、500错误页面的示例代码
Mar 08 Python
Python 解决火狐浏览器不弹出下载框直接下载的问题
Mar 09 Python
python 双循环遍历list 变量判断代码
May 04 Python
pytorch 预训练模型读取修改相关参数的填坑问题
Jun 05 Python
python实现集中式的病毒扫描功能详解
Jul 09 #Python
python 图片去噪的方法示例
Jul 09 #Python
python 使用plt画图,去除图片四周的白边方法
Jul 09 #Python
浅谈Python小波分析库Pywavelets的一点使用心得
Jul 09 #Python
python basemap 画出经纬度并标定的实例
Jul 09 #Python
python实现列表中最大最小值输出的示例
Jul 09 #Python
python实现基于朴素贝叶斯的垃圾分类算法
Jul 09 #Python
You might like
Terran热键控制
2020/03/14 星际争霸
PHP中文件读、写、删的操作(PHP中对文件和目录操作)
2012/03/06 PHP
PHP 查找字符串常用函数介绍
2012/06/07 PHP
PHP自定义大小验证码的方法详解
2013/06/07 PHP
PHP入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等)
2016/09/11 PHP
浅谈php中变量的数据类型判断函数
2017/03/04 PHP
解决Yii2邮件发送结果返回成功,但接收不到邮件的问题
2017/05/23 PHP
php实现简单的权限管理的示例代码
2017/08/25 PHP
Yii2处理密码加密及验证的方法
2019/05/12 PHP
PHP+fiddler抓包采集微信文章阅读数点赞数的思路详解
2019/12/20 PHP
jquery实现树形菜单完整代码
2015/12/29 Javascript
JavaScript开发Chrome浏览器扩展程序UI的教程
2016/05/16 Javascript
jQuery文字轮播特效
2017/02/12 Javascript
原生javascript移动端滑动banner效果
2017/03/10 Javascript
PHP自动加载autoload和命名空间的应用小结
2017/12/01 Javascript
JS实现简易留言板(节点操作)
2020/03/16 Javascript
在vue中使用vant TreeSelect分类选择组件操作
2020/11/02 Javascript
[08:29]DOTA2每周TOP10 精彩击杀集锦vol.7
2014/06/25 DOTA
[52:05]EG vs OG 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
python文件操作整理汇总
2014/10/21 Python
详解Python中的from..import绝对导入语句
2016/06/21 Python
Mac中Python 3环境下安装scrapy的方法教程
2017/10/26 Python
关于python 的legend图例,参数使用说明
2020/04/17 Python
Python tkinter之ComboBox(下拉框)的使用简介
2021/02/05 Python
Ellos瑞典官网:北欧地区时尚、美容和住宅领域领先的电子商务网站
2019/11/21 全球购物
请用用Java代码写一个堆栈
2012/01/26 面试题
如何清空Session
2015/02/23 面试题
会计学个人自荐信模板
2013/12/13 职场文书
经济类毕业生求职信
2014/06/26 职场文书
社区党建工作汇报材料
2014/08/14 职场文书
接待员岗位职责
2015/02/13 职场文书
学生会主席任命书
2015/09/21 职场文书
小学一年级班主任工作经验交流材料
2015/11/02 职场文书
共青团优秀团员申请书(范文)
2019/08/15 职场文书
深入探讨opencv图像矫正算法实战
2021/05/21 Python
MySQL8.0无法启动3534的解决方法
2021/06/03 MySQL