php中pandans,Python地信专题 | 基于geopandas的空间数据分析-文件IO篇
本文對應代碼和數據已上傳至我的Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes
1 簡介
在上一篇文章中我們對geopandas中的坐標參考系有了較為深入的學習,而在日常空間數據分析工作中矢量文件的讀入和寫出,是至關重要的環節。
作為基于geopandas的空間數據分析系列文章的第三篇,通過本文你將會學習到geopandas中的文件IO。
2 文件IO
2.1 矢量文件的讀入
geopandas將fiona作為操縱矢量數據讀寫功能的后端。
使用geopandas.read_file()讀取對應類型文件,而在后端實際上是使用fiona.open來讀入數據,即兩者參數是保持一致的,讀入的數據自動轉換為GeoDataFrame。
下面是geopandas.read_file()主要參數:
filename:str類型,傳入文件對應的路徑或url
layer:str類型,當要讀入的數據格式為地理數據庫.gdb或QGIS中的.gpkg時,傳入對應圖層的名稱
下面結合上述參數,來介紹一下使用geopandas.read_file()在不同情況下讀取常見格式矢量數據的方法。
使用到的示例數據為中國地圖,CRS為EPSG:4326。
本文使用到的所有數據都可以在文章開頭提及的Github倉庫對應本文路徑下找到:
圖1
2.1.1 shapefile
作為非常常見的一種矢量文件格式,geopandas對shapefile提供了很好的讀取和寫出支持。
下面分為不同情況來介紹:
完整的shapefile
如圖2,這是一個完整的shapefile:
圖2
使用geopandas來讀取這種形式的shapefile很簡單:
import geopandas as gpd
data = gpd.read_file('geometry/china_provinces/china_provinces.shp')
print(data.crs) # 查看數據對應的crs
data.head() # 查看前5行
圖3
缺少投影的shapefile
當shapefile中缺失.prj文件時,使用geopandas讀入后形成的GeoDataFrame會缺失crs屬性:
圖4
如果已經知道數據對應的CRS,可以在讀入數據后補充上crs信息以進行其他操作:
import pyproj
data.crs = pyproj.CRS.from_user_input('EPSG:4326')
data.crs
圖5
直接讀取文件夾
當文件夾下只有單個shapefile時,可以直接讀取該文件夾:
圖6
讀取zip壓縮包中的文件
geopandas通過傳入特定語法格式的文件路徑信息,以支持直接讀取.zip格式壓縮包中的shapefile文件,主要分為兩種情況。
當文件在壓縮包內的根目錄時,使用下面的語法規則來讀取數據:
zip://路徑/xxx.zip
譬如我們要讀取圖7所示的壓縮包內文件:
圖7
按照對應的語法規則,讀取該類型數據方式如下:
圖8
而當文件在壓縮包內的文件夾中時,如圖9:
圖9
使用下面的語法規則來讀取數據:
zip://路徑/xxx.zip!壓縮包內指定文件路徑
將上述語法運用到上述文件:
圖10
2.1.2 gdb與gpkg
對于Arcgis中的地理數據庫gdb,以及QGIS中的GeoPackage,要讀取其包含的矢量數據,就要涉及到圖層的概念。
對應geopandas.read_file()的layer參數,只需要將gdb或gpkg文件路徑作為filename參數,再將對應的圖層名稱作為layer參數傳入:
gdb
data = gpd.read_file('geometry/china_provinces.gdb',
layer='china_provinces')
print(data.crs) # 查看數據對應的crs
data.head() # 查看前5行
圖11
gpkg
類似讀入gdb文件:
data = gpd.read_file('geometry/china_provinces.gpkg',
layer='china_provinces',
encoding='utf-8')
print(data.crs) # 查看數據對應的crs
data.head() # 查看前5行
圖12
2.1.3 GeoJSON
作為web地圖中最常使用的矢量數據格式,GeoJSON幾乎被所有在線地圖框架作為數據源格式,在geopandas中讀取GeoJSON非常簡單,只需要傳入文件路徑名稱即可。
下面我們來讀入圖13所示的文件:
圖13
圖14
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')
圖15
可以看到只有跟紅色框有相交的幾何對象被讀入。
蒙版過濾
蒙版過濾和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')
圖16
可以看到只有跟紅色多邊形相交的幾何對象被讀入。
行過濾
行過濾的功能就比較簡單,通過參數rows控制讀入原數據的前若干行,可以用于在讀取大型數據時先快速查看前幾行以了解整個數據的格式:
圖17
2.2 矢量文件的寫出
在geopandas中使用to_file()來將GeoDataFrame或GeoSeries寫出為矢量文件,主要支持shapefile、GeoJSON以及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:
圖18
而如果導出的文件名不加后綴擴展名,則會生成包含在新目錄下的shapefile:
data.to_file('output/output_shapefile',
driver='ESRI Shapefile',
encoding='utf-8')
圖19
也可以向指定的文件夾下追加圖層:
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')
圖20
GeoPackage
對于gdb文件,由于ESRI的限制,暫時無法在開源的geopandas中導出。
但我們可以用QGIS中的GeoPackage作為替代方案(開源世界萬歲O(∩_∩)O~~),只需要將driver參數設置為GPKG即可。
這里需要注意一個bug:在使用geopandas導出GeoPackage文件時,可能會出現圖21所示錯誤:
圖21
但我觀察到即使出現了上述錯誤,GeoPackage文件也是成功保存到路徑下的且整個程序并未被打斷,因此可以無視上述錯誤:
圖22
GeoJSON
寫出為GeoJSON非常容易,只需要設置driver='GeoJSON'即可:
圖23
以上就是本文的全部內容,如有筆誤望指出!
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的php中pandans,Python地信专题 | 基于geopandas的空间数据分析-文件IO篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国银行淘宝联名卡怎么样?积分、好礼享不
- 下一篇: php改成IP连接数据库,thinkph