(数据科学学习手札77)基于geopandas的空间数据分析——文件IO

本文对应代码和数据已上传至个人Github仓库https://github.com/CNFeffery/DataScienceStudyNoteshtml

1 简介

  在上一篇文章中咱们对geopandas中的坐标参考系有了较为深刻的学习,而在平常空间数据分析工做中矢量文件的读入和写出,是相当重要的环节。python

  做为基于geopandas的空间数据分析系列文章的第三篇,经过本文你将会学习到geopandas中的文件IOgit

2 文件IO

2.1 矢量文件的读入

  geopandasfiona做为操纵矢量数据读写功能的后端,使用geopandas.read_file()读取对应类型文件,而在后端其实是使用fiona.open来读入数据,即二者参数是保持一致的,读入的数据自动转换为GeoDataFrame,下面是geopandas.read_file()主要参数:github

filename:str类型,传入文件对应的路径或url layer:str类型,当要读入的数据格式为地理数据库.gdbQGIS中的.gpkg时,传入对应图层的名称web

  下面结合上述参数,来介绍一下使用geopandas.read_file()在不一样状况下读取常见格式矢量数据的方法,使用到的示例数据为中国地图,CRSEPSG:4326,本文使用到的全部数据均可以在文章开头说起的Github仓库对应本文路径下找到:数据库

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225132841878-1892879651.png" style="zoom:75%;"></img></center><center><font size=2>图1</font></center>json

2.1.1 shapefile

  做为很是常见的一种矢量文件格式,geopandasshapefile提供了很好的读取和写出支持,下面分为不一样状况来介绍:后端

  • 完整的shapefile

  如图2,这是一个完整的shapefilebash

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225132850233-1458701775.png" style="zoom:100%;"></img></center><center><font size=2>图2</font></center>框架

  使用geopandas来读取这种形式的shapefile很简单:

import geopandas as gpd

data = gpd.read_file('geometry/china_provinces/china_provinces.shp')
print(data.crs) # 查看数据对应的crs
data.head() # 查看前5行

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225132859933-246445972.png" style="zoom:80%;"></img></center><center><font size=2>图3</font></center>

  • 缺乏投影的shapefile

  当shapefile中缺失.prj文件时,使用geopandas读入后造成的GeoDataFrame会缺失crs属性:   

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225132909814-786739378.png" style="zoom:80%;"></img></center><center><font size=2>图4</font></center>

  若是已经知道数据对应的CRS,能够在读入数据后补充上crs信息以进行其余操做:

import pyproj

data.crs = pyproj.CRS.from_user_input('EPSG:4326')
data.crs

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225132918753-807764122.png" style="zoom:80%;"></img></center><center><font size=2>图5</font></center>

  • 直接读取文件夹

  当文件夹下只有单个shapefile时,能够直接读取该文件夹:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225132934773-490544145.png" style="zoom:80%;"></img></center><center><font size=2>图6</font></center>

  • 读取zip压缩包中的文件

  geopandas经过传入特定语法格式的文件路径信息,以支持直接读取.zip格式压缩包中的shapefile文件,主要分为两种状况。   当文件在压缩包内的根目录时,使用下面的语法规则来读取数据:

zip://路径/xxx.zip

  譬如咱们要读取图7所示的压缩包内文件:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225132945818-1711366862.png" style="zoom:75%;"></img></center><center><font size=2>图7</font></center>

  按照对应的语法规则,读取该类型数据方式以下:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225132956893-2043405839.png" style="zoom:80%;"></img></center><center><font size=2>图8</font></center>

  而当文件在压缩包内的文件夹中时,如图9:   

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133009647-471588474.png" style="zoom:80%;"></img></center><center><font size=2>图9</font></center>

  使用下面的语法规则来读取数据:

zip://路径/xxx.zip!压缩包内指定文件路径

  将上述语法运用到上述文件:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133019138-658110373.png" style="zoom:80%;"></img></center><center><font size=2>图10</font></center>

2.1.2 gdb与gpkg

  对于Arcgis中的地理数据库gdb,以及QGIS中的GeoPackage,要读取其包含的矢量数据,就要涉及到图层的概念,对应geopandas.read_file()layer参数,只须要将gdbgpkg文件路径做为filename参数,再将对应的图层名称做为layer参数传入:

  • gdb
data = gpd.read_file('geometry/china_provinces.gdb', 
                     layer='china_provinces')
print(data.crs) # 查看数据对应的crs
data.head() # 查看前5行

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133031253-163405040.png" style="zoom:80%;"></img></center><center><font size=2>图11</font></center> - **gpkg**

  相似读入gdb文件:

data = gpd.read_file('geometry/china_provinces.gpkg', 
                     layer='china_provinces',
                     encoding='utf-8')
print(data.crs) # 查看数据对应的crs
data.head() # 查看前5行

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133039558-1881763371.png" style="zoom:80%;"></img></center><center><font size=2>图12</font></center>

2.1.3 GeoJSON

  做为web地图中最常使用的矢量数据格式,GeoJSON几乎被全部在线地图框架做为数据源格式,在geopandas中读取GeoJSON很是简单,只须要传入文件路径名称便可,下面咱们来读入图13所示的文件:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133049563-1354089913.png" style="zoom:80%;"></img></center><center><font size=2>图13</font></center>

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133057942-686792753.png" style="zoom:80%;"></img></center><center><font size=2>图14</font></center>

2.1.4 过滤

  geopandas在0.1.0版本中新增了bbox过滤,在0.7.0版本中新增了蒙版过滤行过滤功能,能够辅助咱们根据本身的须要读入原始数据中的子集,下面一一进行介绍:

  • bbox过滤

  bbox过滤容许咱们在read_file()中传入一个边界框做为参数bbox,格式为(左下角x, 左下角y, 右上角x, 右上角y),这样在读入的过程当中只会保留几何对象与bbox有相交的数据记录,下面咱们仍然以上文中使用过的中国地图数据为例,咱们在读入的过程当中,传入边界框:

from shapely import geometry

data = gpd.read_file('geometry/china_provinces.json',
                    bbox=(100, 20, 110, 30))

%matplotlib widget
ax = data.plot()
# 绘制bbox框示意
ax = gpd.GeoSeries([geometry.box(minx=100, 
                                 miny=20, 
                                 maxx=110, 
                                 maxy=30).boundary]).plot(ax=ax, color='red')

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133105453-1581916323.png" style="zoom:80%;"></img></center><center><font size=2>图15</font></center>

  能够看到只有跟红色框有相交的几何对象被读入。

  • 蒙版过滤

  蒙版过滤bbox过滤功能类似,都是筛选与指定区域相交的数据记录,不一样的是蒙版过滤经过mask参数能够传入任意形状的多边形,再也不像bbox过滤那样只接受矩形:

data = gpd.read_file('geometry/china_provinces.json',
                    mask=geometry.Polygon([(100, 20), (110, 30), (120, 20)]))

ax = data.plot()
# 绘制bbox框示意
ax = gpd.GeoSeries([geometry.Polygon([(100, 20), 
                                      (110, 30), 
                                      (120, 20)]).boundary]).plot(ax=ax, color='red')

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133113158-1198225670.png" style="zoom:80%;"></img></center><center><font size=2>图16</font></center>

  能够看到只有跟红色多边形相交的几何对象被读入。

  • 行过滤

  行过滤的功能就比较简单,经过参数rows控制读入原数据的前若干行,能够用于在读取大型数据时先快速查看前几行以了解整个数据的格式:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133120283-1743802169.png" style="zoom:80%;"></img></center><center><font size=2>图17</font></center>

2.2 矢量文件的写出

  在geopandas中使用to_file()来将GeoDataFrameGeoSeries写出为矢量文件,主要支持shapefileGeoJSON以及GeoPackage,不像geopandas.read_file()能够根据传入的文件名称信息自动推断类型,咱们在写出矢量数据时就须要使用driver参数来声明文件类型:

  • ESRI Shapefile

  咱们将上文最后一次读入的GeoDataFrame写出为ESRI Shapefile,设置driver参数为ESRI Shapefile,若是你对文件编码有要求,这里可使用encoding参数来指定,譬如这里咱们指定为utf-8

'''在工程根目录下建立output文件夹'''
import os

try:
    os.mkdir('output')
except FileExistsError:
    pass
    
data.to_file('output/output.shp', 
             driver='ESRI Shapefile',
             encoding='utf-8')

  能够看到在output文件夹下,成功导出了完整的shapefile

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133129223-38916263.png" style="zoom:80%;"></img></center><center><font size=2>图18</font></center>

  而若是导出的文件名不加后缀扩展名,则会生成包含在新目录下的shapefile

data.to_file('output/output_shapefile', 
             driver='ESRI Shapefile',
             encoding='utf-8')

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133137048-1202954666.png" style="zoom:80%;"></img></center><center><font size=2>图19</font></center>

  也能够向指定的文件夹下追加图层:

data.to_file('output/output_shapefile_multi_layer', 
             driver='ESRI Shapefile',
             layer='layer1',
             encoding='utf-8')

data.to_file('output/output_shapefile_multi_layer', 
             driver='ESRI Shapefile',
             layer='layer2',
             encoding='utf-8')

data.to_file('output/output_shapefile_multi_layer', 
             driver='ESRI Shapefile',
             layer='layer3',
             encoding='utf-8')

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133145283-925661579.png" style="zoom:80%;"></img></center><center><font size=2>图20</font></center>

  • GeoPackage

  对于gdb文件,因为ESRI的限制,暂时没法在开源的geopandas中导出,但咱们能够用QGIS中的GeoPackage做为替代方案(开源世界万岁O(∩_∩)O~~),只须要将driver参数设置为GPKG便可,这里须要注意一个bug:在使用geopandas导出GeoPackage文件时,可能会出现图21所示错误:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133154163-554486077.png" style="zoom:80%;"></img></center><center><font size=2>图21</font></center>

  但我观察到即便出现了上述错误,GeoPackage文件也是成功保存到路径下的且整个程序并未被打断,所以能够无视上述错误:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133202343-273258812.png" style="zoom:80%;"></img></center><center><font size=2>图22</font></center>

  • GeoJSON

  写出为GeoJSON很是容易,只须要设置driver='GeoJSON'便可:

<center><img src="https://img2018.cnblogs.com/blog/1344061/202002/1344061-20200225133213773-1457528027.png" style="zoom:80%;"></img></center><center><font size=2>图23</font></center>

  以上就是本文的所有内容,若有笔误望指出!

原文出处:https://www.cnblogs.com/feffery/p/12301966.html

相关文章
相关标签/搜索