利用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 相关文章推荐
python3使用urllib示例取googletranslate(谷歌翻译)
Jan 23 Python
Python的另外几种语言实现
Jan 29 Python
python实现登陆知乎获得个人收藏并保存为word文件
Mar 16 Python
python数字图像处理之高级形态学处理
Apr 27 Python
Python实现多属性排序的方法
Dec 05 Python
使用pip安装python库的多种方式
Jul 31 Python
详解Python图像处理库Pillow常用使用方法
Sep 02 Python
基于Tensorflow:CPU性能分析
Feb 10 Python
python之生成多层json结构的实现
Feb 27 Python
Django跨域资源共享问题(推荐)
Mar 09 Python
python实现遍历文件夹图片并重命名
Mar 23 Python
pytorch实现手写数字图片识别
May 20 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
中国收音机工业发展史
2021/03/02 无线电
PHP使用CURL实现多线程抓取网页
2015/04/30 PHP
WordPress导航菜单的滚动和淡入淡出效果的实现要点
2015/12/14 PHP
从性能方面考虑PHP下载远程文件的3种方法
2015/12/29 PHP
php实现批量修改文件名称的方法
2016/07/23 PHP
JavaScript中prototype为对象添加属性的误区介绍
2013/10/15 Javascript
jQuery判断数组是否包含了指定的元素
2015/03/10 Javascript
js实现Select头像选择实时预览代码
2015/08/17 Javascript
jQuery实现鼠标双击Table单元格变成文本框及输入内容后更新到数据库的方法
2015/11/25 Javascript
易被忽视的js事件问题总结
2016/05/14 Javascript
JavaScript实现的XML与JSON互转功能详解
2017/02/16 Javascript
基于react框架使用的一些细节要点的思考
2017/05/31 Javascript
微信小程序使用slider设置数据值及switch开关组件功能【附源码下载】
2017/12/09 Javascript
vue配置文件实现代理v2版本的方法
2019/06/21 Javascript
Vue2.X和Vue3.0数据响应原理变化的区别
2019/11/07 Javascript
详解JS预解析原理
2020/06/16 Javascript
微信小程序实现发微博功能的示例代码
2020/06/24 Javascript
JavaScript实现网页计算器功能
2020/10/29 Javascript
[01:41]DOTA2超级联赛专访YYF 称一辈子难忘TI2
2013/05/28 DOTA
[07:57]DOTA2热力大趴狂欢夜 广州站活动回顾
2013/11/27 DOTA
Python3.X 线程中信号量的使用方法示例
2017/07/24 Python
numpy matrix和array的乘和加实例
2018/06/28 Python
不到40行代码用Python实现一个简单的推荐系统
2019/05/10 Python
详解如何在cmd命令窗口中搭建简单的python开发环境
2019/08/29 Python
在脚本中单独使用django的ORM模型详解
2020/04/01 Python
python 异步async库的使用说明
2020/05/04 Python
python里的单引号和双引号的有什么作用
2020/06/17 Python
Python numpy矩阵处理运算工具用法汇总
2020/07/13 Python
雷蛇美国官网:Razer
2020/04/03 全球购物
暑期社会实践感言
2014/02/25 职场文书
2014年学生会部门工作总结
2014/11/07 职场文书
支行行长岗位职责
2015/02/15 职场文书
法人身份证明书
2015/06/18 职场文书
财产分割协议书
2016/03/22 职场文书
学习计划是什么
2019/04/30 职场文书
python的html标准库
2022/04/29 Python