June 13, 2020

Shapefile属性操作之增

版权声明:本文为博主原创文章,转载请注明原文出处!

作者:阿振

写作时间: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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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

方法总结

下面我们来对上面的代码进行一个方法的总结:

  1. 首先,我们使用ogr.Open()函数打开Shapefile数据,注意我们要设置update参数为True,即允许GDAL更新我们的原始数据。
  2. 使用ogr.FieldDefn()函数新建一个字段,然后添加到layer图层中。注意我们这里新建的字段的类型是字符串类型ogr.OFTString,当然我们还可以新建其他类型的字段,例如整形ogr.OFTInteger,实数形ogr.OFTReal,日期型ogr.OFTDate等。一般对于字符串类型,我们还需要设置字符串的宽度。
  3. 接下来我们遍历layer中的feature,使用SetField()方法设置属性值。记得添加完属性值以后,需要使用SetFeature()方法将当前feature更新到涂层layer中去。