利用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 时间处理datetime实例
Sep 06 Python
使用beaker让Facebook的Bottle框架支持session功能
Apr 23 Python
Python 实现数据库(SQL)更新脚本的生成方法
Jul 09 Python
Python内置函数delattr的具体用法
Nov 23 Python
Python实现替换文件中指定内容的方法
Mar 19 Python
对python以16进制打印字节数组的方法详解
Jan 24 Python
python如何获取列表中每个元素的下标位置
Jul 01 Python
解决django同步数据库的时候app models表没有成功创建的问题
Aug 09 Python
Python return语句如何实现结果返回调用
Oct 15 Python
Python之qq自动发消息的示例代码
Feb 18 Python
python单例模式的应用场景实例讲解
Feb 24 Python
python区块链实现简版工作量证明
May 25 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
Win2000+Apache+MySql+PHP4+PERL安装使用小结
2006/10/09 PHP
基于pear auth实现登录验证
2010/02/26 PHP
php图片上传存储源码并且可以预览
2011/08/26 PHP
ThinkPHP打开验证码页面显示乱码的解决方法
2014/12/18 PHP
关于PHP中字符串与多进制转换函数的实例代码
2016/11/03 PHP
php 7新特性之类型申明详解
2017/06/06 PHP
Thinkphp5+uploadify实现的文件上传功能示例
2018/05/26 PHP
WebGame《逆转裁判》完整版 代码下载(1月24日更新)
2007/01/29 Javascript
ajax 缓存 问题 requestheader
2010/08/01 Javascript
纯文字版返回顶端的js代码
2013/08/01 Javascript
JS简单循环遍历json数组的方法
2016/04/22 Javascript
jQuery实现下拉菜单(内容为时间)的实时更新及图表的随动更新的方法
2016/07/07 Javascript
使用jquery/js获取iframe父子级、同级获取元素的方法
2016/08/05 Javascript
基于Vue.js实现简单搜索框
2020/03/26 Javascript
jQuery常见的选择器及用法介绍
2016/12/20 Javascript
原生JS发送异步数据请求
2017/06/08 Javascript
JS去掉字符串末尾的标点符号及删除最后一个字符的方法
2017/10/24 Javascript
jquery动态添加带有样式的HTML标签元素方法
2018/02/24 jQuery
微信小程序使用form表单获取输入框数据的实例代码
2018/05/17 Javascript
vue实现引入本地json的方法分析
2018/07/12 Javascript
新版小程序登录授权的方法
2018/12/12 Javascript
简述Vue中容易被忽视的知识点
2019/12/09 Javascript
微信小程序实现手指拖动选项排序
2020/04/22 Javascript
[01:14:12]2018DOTA2亚洲邀请赛4.7 总决赛 LGD vs Mineski 第二场
2018/04/09 DOTA
python实现带验证码网站的自动登陆实现代码
2015/01/12 Python
Python3处理文件中每个词的方法
2015/05/22 Python
PyGame贪吃蛇的实现代码示例
2018/11/21 Python
使用Python的SymPy库解决数学运算问题的方法
2019/03/27 Python
python关于倒排列的知识点总结
2020/10/13 Python
Canvas实现保存图片到本地的示例代码
2018/06/28 HTML / CSS
印度最好的在线药品订购网站:PharmEasy
2018/11/30 全球购物
三年级班级文化建设方案
2014/05/04 职场文书
高一化学教学反思
2016/02/22 职场文书
SpringBoot整合JWT的入门指南
2021/06/29 Java/Android
Python编程中Python与GIL互斥锁关系作用分析
2021/09/15 Python
Windows 11要来了?微软文档揭示Win11太阳谷 / Win10有两个不同版本
2021/11/21 数码科技