版權聲明:本文爲博主原創文章,轉載請註明原文出處!
作者:阿振
寫作時間:2020-06-13 又是一個週末
開篇
《Python空間數據處理實戰》系列的博文好久都沒有更新了,今天乘週末有點時間,補了個覺,然後寫幾篇博文。
關於Python空間數據處理,如果大家有什麼想看到的內容,歡迎評論區留言,我會增加一些大家需要的內容!
今天我打算用四篇博客簡要介紹一下如何對空間矢量數據的屬性數據進行操作。對於屬性數據,我們可以簡單將其看作一個二維表格,學過數據庫的朋友,可能會想到關係數據庫的概念。是的,我們現在的空間矢量數據的屬性數據大部分就是以關係表的形式進行存儲的。而對於關係數據庫的操作,常用的就是增刪改查(CRUD,即Create,Retrieve,Update,Delete)操作。
這篇博文單講Create增加操作,使用的工具還是我們的GDAL庫。
案例介紹
我還是喜歡用案例的方式進行知識的講解。這裏我們要處理的數據是中國地圖分省的矢量Shapefile,是一個面狀數據。該數據有一個NAME
字段,給出了每個省的名稱。然後我們需要給給數據增加一個屬性字段Abbr
,用以表示每個省的簡稱。
要完成這項工作,我們首先需要建立一個省份名稱到簡稱的字典,方便程序查詢。然後讀取原始數據,新建一個屬性字段Abbr
,然後遍歷數據中的每個Feature要素,取出NAME
,再根據字典查詢到當前NAME
對應的Abbr
填充進對應的字段即可。
代碼展示
Talk is cheap. Show me the code.
from osgeo import ogr
ogr.UseExceptions()
# 首先定義每個省全稱到簡稱的映射字典
names = {
'北京': '京',
'天津': '津',
'重慶': '渝',
'上海': '滬',
'河北': '冀',
'山西': '晉',
'遼寧': '遼',
'吉林': '吉',
'黑龍江': '黑',
'江蘇': '蘇',
'浙江': '浙',
'安徽': '皖',
'福建': '閩',
'江西': '贛',
'山東': '魯',
'河南': '豫',
'湖北': '鄂',
'湖南': '湘',
'廣東': '粵',
'海南': '瓊',
'四川': '川/蜀',
'貴州': '黔/貴',
'雲南': '雲/滇',
'陝西': '陝/秦',
'甘肅': '甘/隴',
'青海': '青',
'臺灣': '臺',
'內蒙古': '蒙',
'廣西': '桂',
'寧夏': '寧',
'新疆': '新',
'西藏': '藏',
'香港': '港',
'澳門': '澳'
}
# 打開一個Shapefile文件獲取屬性定義
ds: ogr.DataSource = ogr.Open('../data/省級行政區.shp', update=True)
layer: ogr.Layer = ds.GetLayer()
defs: ogr.FeatureDefn = layer.GetLayerDefn()
for i in range(defs.GetFieldCount()):
defn: ogr.FieldDefn = defs.GetFieldDefn(i)
print(f'{defn.GetName()} -> {defn.GetType()} -> {defn.GetWidth()}')
# 添加一個省簡稱的字段
field: ogr.FieldDefn = ogr.FieldDefn('Abbr', ogr.OFTString)
field.SetWidth(5)
layer.CreateField(field)
# 填充屬性值
for feature in layer:
name: str = feature.GetField('NAME')
feature.SetField('Abbr', names.get(name, ''))
# 修改完了記得Set一下
layer.SetFeature(feature)
# 關閉數據集
ds = None
方法總結
下面我們來對上面的代碼進行一個方法的總結:
- 首先,我們使用
ogr.Open()
函數打開Shapefile數據,注意我們要設置update
參數爲True
,即允許GDAL更新我們的原始數據。 - 使用
ogr.FieldDefn()
函數新建一個字段,然後添加到layer
圖層中。注意我們這裏新建的字段的類型是字符串類型ogr.OFTString
,當然我們還可以新建其他類型的字段,例如整形ogr.OFTInteger
,實數形ogr.OFTReal
,日期型ogr.OFTDate
等。一般對於字符串類型,我們還需要設置字符串的寬度。 - 接下來我們遍歷
layer
中的feature
,使用SetField()
方法設置屬性值。記得添加完屬性值以後,需要使用SetFeature()
方法將當前feature
更新到塗層layer
中去。