本文對應代碼和數據已上傳至個人
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