版權聲明:本文爲博主原創文章,轉載請註明原文出處!
作者:阿振
寫作時間:2020-06-13 夜
開篇
在前面幾篇博文中,我們分別介紹了矢量空間數據的屬性數據的增(CREATE)刪(DELETE)改(UPDATE)操作,這篇博文我們來聊聊屬性數據的查詢(Retrieve)操作。
案例介紹
我們還是使用之前的分省Shapefile數據,主要包含每個省的一些統計信息。下面以兩個案例進行介紹:
- 從給定數據中查詢中學數量(HighSchool字段)大於1萬所的省份
- 從給定數據中查詢中學數量最多的省份
下面簡單說一下使用GDAL進行屬性數據查詢的兩種思路:
- 因爲矢量數據的屬性一般都是以關係表進行保存的,所以我們可以使用關係數據庫查詢語言SQL進行數據查詢。GDAL支持部分SQL查詢功能。
- 我們可以遍歷圖層Layer中包含的所有Feature要素,然後讀取要素的屬性數據進行篩選過濾得到我們想要的結果。
SQL查詢方式
代碼展示
Talk is cheap. Show me the code.
首先,我們來看看使用SQL進行查詢的代碼。
from osgeo import ogr
ogr.UseExceptions()
ds: ogr.DataSource = ogr.Open('../data/Provinces.shp')
# 注意Layer的名稱不能包含中文
layer: ogr.Layer = ds.GetLayer()
# 選擇出中學數量大於1萬所的省份
query: str = f'SELECT NAME, HighSchool FROM {layer.GetName()} WHERE HighSchool > 10000'
selected: ogr.Layer = ds.ExecuteSQL(query)
# 這裏的Feature中只包含兩個屬性NAME和HighSchool
for feature in selected:
print(feature.GetField('NAME'))
# 選擇出中學數量最多的省份
# 我嘗試使用MAX函數和嵌套的SELECT語句進行實現,但是執行報錯,應該是OGR不支持嵌套的SQL查詢
query: str = f'SELECT NAME, HighSchool FROM {layer.GetName()} ORDER BY HighSchool DESC'
selected: ogr.Layer = ds.ExecuteSQL(query)
print(selected.GetFeature(0).GetField('NAME'))
print(selected.GetFeature(0).GetField('HighSchool'))
方法總結
- 首先我們使用
ogr.Open()
函數讀取數據,使用GetLayer()
方法獲取圖層 - 然後構造SQL查詢語句,圖層名稱對應的是SQL語句中的表名。注意如果圖層名稱爲中文,查詢會失敗。
- 然後使用
ExecuteSQL()
方法執行查詢,得到的查詢結果仍然是一個ogr.Layer
圖層類,但是圖層中的要素屬性只包含我們查詢語句中指定的字段 - 對於第二個案例,我們本來可以使用一個嵌套的SELECT查詢語句以及MAX聚合函數得到最大的中學數量,但是使用嵌套的SQL查詢執行會失敗。所以我在第二個案例中使用了ORDER BY子句進行排序,然後查詢結果的第一個要素就是我們尋找的最大值。
遍歷Feature要素方式
代碼展示
我們再來看使用遍歷Feature要素的方法。
from osgeo import ogr
ogr.UseExceptions()
ds: ogr.DataSource = ogr.Open('../data/Provinces.shp')
# 注意Layer的名稱不能包含中文
layer: ogr.Layer = ds.GetLayer()
# 使用filter函數對要素屬性進行過濾
selected = list(filter(lambda f: f.GetField('HighSchool') > 10000, layer))
for feature in selected:
print(feature.GetField('NAME'))
# 使用sorted方法對要素進行自定義排序,這裏使用逆序
selected = sorted(layer, key=lambda f: f.GetField('HighSchool'), reverse=True)
print(selected[0].GetField('NAME'))
print(selected[0].GetField('HighSchool'))
方法總結
- 使用遍歷Feature要素的方法進行查詢是我們在獲取了圖層包含的所有Feature要素集合以後,使用Python內置的函數對該集合進行過濾,排序等操作得到我們想要的查詢結果。
filter()
函數的第一個參數是一個自定義函數,第二個參數是一個可迭代對象iterable。該函數會遍歷可迭代對象將滿足第一個自定義函數的值過濾出來。sorted()
函數包含三個參數(後兩個可選),第一個參數是一個可迭代對象iterable,第二個參數是用於自定義排序的函數,第三個參數指定是否逆序。sorted()
函數的返回值是一個list
對象。- 我更喜歡使用第二種遍歷的方式,因爲更方便調試一些。當然如果對SQL語言熟悉的同學,可能更喜歡SQL這種聲明式編程的方式。