本文对应代码和数据已上传至个人
Github
仓库https://github.com/CNFeffery/DataScienceStudyNoteshtml
在上一篇文章中咱们对geopandas
中的坐标参考系有了较为深刻的学习,而在平常空间数据分析工做中矢量文件的读入和写出,是相当重要的环节。python
做为基于geopandas的空间数据分析系列文章的第三篇,经过本文你将会学习到geopandas
中的文件IO。git
geopandas
将fiona
做为操纵矢量数据读写功能的后端,使用geopandas.read_file()
读取对应类型文件,而在后端其实是使用fiona.open
来读入数据,即二者参数是保持一致的,读入的数据自动转换为GeoDataFrame
,下面是geopandas.read_file()
主要参数:github
filename:str类型,传入文件对应的路径或url layer:str类型,当要读入的数据格式为地理数据库
.gdb
或QGIS
中的.gpkg
时,传入对应图层的名称web
下面结合上述参数,来介绍一下使用geopandas.read_file()
在不一样状况下读取常见格式矢量数据的方法,使用到的示例数据为中国地图,CRS
为EPSG: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
做为很是常见的一种矢量文件格式,geopandas
对shapefile
提供了很好的读取和写出支持,下面分为不一样状况来介绍:后端
如图2,这是一个完整的shapefile
:bash
<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
中缺失.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>
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>
对于Arcgis
中的地理数据库gdb
,以及QGIS
中的GeoPackage
,要读取其包含的矢量数据,就要涉及到图层的概念,对应geopandas.read_file()
的layer
参数,只须要将gdb
或gpkg
文件路径做为filename
参数,再将对应的图层名称做为layer
参数传入:
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>
做为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>
geopandas
在0.1.0版本中新增了bbox过滤,在0.7.0版本中新增了蒙版过滤和行过滤功能,能够辅助咱们根据本身的须要读入原始数据中的子集,下面一一进行介绍:
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>
在geopandas
中使用to_file()
来将GeoDataFrame
或GeoSeries
写出为矢量文件,主要支持shapefile
、GeoJSON
以及GeoPackage
,不像geopandas.read_file()
能够根据传入的文件名称信息自动推断类型,咱们在写出矢量数据时就须要使用driver
参数来声明文件类型:
咱们将上文最后一次读入的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>
对于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
很是容易,只须要设置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