本文章主要介绍ArcGis中字段计算器的使用方法,(含文本处理、数值处理、组合计算、多要素关联计算等)并结合实际案例,对具体的情况进行分析讲解。
由于Esri在ArcGis Pro中取消了VB脚本解析程序,本文章中实现复杂功能的情况主要使用Python解析程序。其他情形,vb和python都会有介绍。
若有疑问,或希望博主展开的部分,可评论留言。
下图,字段计算器页面中:
1:解析程序; 2:表达式; 3:代码块;
4:被计算字段(右键点击并选择“字段计算器”的字段)
目 录
一、字段计算器的初步应用
1.1.字段计算器中的vb和python解析程序的介绍与区别
1.1.1.不同解析程序对应的“空”值
1.2.字段计算器的基本使用方法
1.2.1.简单值填入
1.2.2.只计算一部分要素
1.3.处理文本(复杂案例见2.2)
1.3.1.文本的简单组合和提取
1.3.2.python关于字符串提取的逻辑解释
二、复杂案例解析
2.0.字段计算器中“代码块”的食用方法(仅python,有了解的可跳过)
2.0.1.代码块介绍
2.0.2.通过字段计算器的代码块进行条件判断
2.1.获取图形的属性(面积、长度、XYZ)
2.2.文字提取(复杂情况)
2.2.1.使用python的(index)查找文本内某字符并按规则提取。
2.2.2.使用正则表达式处理符合规则的字符
2.3.从"A"要素中取值,维护"B"要素的字段(A的属性填入B)
其他:
1.不同类型的数据在使用字段计算器时的注意事项
vb和python分别对应的是两种不同的编程语言,字段计算器中的vb与Excel的函数大体上是比较类似的,如Excel内mid函数 =MID(A1,2,3) 对应在字段计算器中就为 mid([字段名称],2,3) ,但在python中就大不一样 !字段名称![1:4]。
提取 “abcdefg” 内的 “bcd”
EXCEL: =MID(A1,2,3)
VB: MID([字段名称],2,3)
python: !字段名称![1:4]
VB:
null
Python:
None
注:Shapefile 属性表内不允许存在“空”值。留空可在计算时引号内不留空
例如:将下图中所有行的文本1字段内填写入“AAA”
两种不同的解析程序如下:
vb: vb中填写入的文本,必须使用英文的双引号括起来,
"AAA"
python: python中的文本单引号,双引号均可
'AAA'
"AAA"
可通过手动选择或按属性选择,选中需要计算的要素,再使用字段计算器即可。
例如:下图,将OBJECTID等于1或等于2的要素,文本test字段中填写入“test”
如上图,蓝色高亮选中要素的文本test字段中被填入“test”。表达式就不写了
纯文本的组合:比较简单,就不上图片了,需要注意的是,在文本组合时vb和python的符号是不一样的。
vb: [文本1] & [文本2]
python: !文本1! + !文本2!
数值与文本组合:使用python时需要注意,将数值使用“str()”类型转换为文本类型,再做组合,否则会报错。
vb: [文本1] & [数值1]
python: !文本1! + str(!数值1!)
文本提取多为数据样例如下图:
例1:提取“文本1”字段中的前3位
表达式:
vb: left( [文本1] ,3)
python: !文本1![:3]
实现后的效果:
例2:提取“文本1”字段中的后3位
vb: right( [文本1] ,3)
python: !文本1![-3:]
实现后的效果:
例3:提取“文本1”字段中从第5位开始向后取3位
vb: mid( [文本1] ,5,3)
python: !文本1![4:7]
实现后的效果:
为什么例1与例2中,python表达式内数值都与我们想提取的位数有关,而例3中,貌似与我们需要提取的位数并无关联。
原因在于,python对字符串取值的顺序与我们常规理解的不一致,如下图所示,字符串A-H与其位置对应关系图。绿色为从左至右的取值位,红为从右往左的取值位。
且使用 [起始位:结束位] 取字符时,取出字符串包含起始位,但不包含结束位,且起始位应当位于结束位左侧:
举几个例子:
# 提取BCD
# 例1:'ABCDEFGH'[1:4]
# 例2:'ABCDEFGH'[-7:-4]
# 例3:'ABCDEFGH'[1:-4]
# 例3:'ABCDEFGH'[-7:4]
以上所有方式,均可返回字符串“BCD”
其他:
# 只提取某一位
例1提取字符D:'ABCDEFGH'[3]
例2提取字符G:'ABCDEFGH'[-2]
# 提取至结尾,或提取至开头
例1提取字符C之前的且不提取C:'ABCDEFGH'[:2]
例2提取字符B之后的且提取B:'ABCDEFGH'[1:]
例3提取字符F之后的且提取F:'ABCDEFGH'[-3:]
例4提取字符E之后的且不提取E:'ABCDEFGH'[-3:]
那么,做个题目吧,有一个不确定长度的字符串,前后都有一个下划线,如何提取下划线之间的内容呢?也就是头尾去掉一个字符(答案写在评论区了,笑)
(虽然本章节部分代码可直接使用,但仍建议对Python有初步的了解后再查看本节)
如下图,在勾选“显示代码块”后展开的输入框1 为“代码块”,输入框 2 为“表达式”,2 与未勾选时的输入框为相同输入框。图中为一个简单的通过调用自定义函数进行字段计算的简单示意。
代码块中:第一行的def 表示定义了一个函数,函数名称为 aa,且这个函数中 有一个名为b的参数。第二行的 return表示返回值,返回 b + 1的结果。
表达式:表示调用代码块中定义的 aa 函数,并将字段 !mj! 的值作为参数 b ,带入函数进行运算。
举例:如Excel中的 left 函数,它的函数名为“left” 它有两个参数,第一个是被提取的值,第二个是需要取值的位数。他的“代码块”已经在软件中内置好了,不需要我们定义,我们只需要在“表达式(单元格)”中输入他的函数名,并填写入所需要的变量,就可以了。 在字段计算器中,就相当于我们在“代码块”中自定义了一个函数。并在表达式中调用它。
数据来源字段如下图,需求,使用字段计算器进行判断,将面积大于1的标记为“面积大于1”,小于等于1的标记为“面积小于等于1”.
代码块及解释:
# 定义函数 aa, 参数1个 名为 b
def aa(b):
# 条件判断,如果 b 大于 1
if b > 1:
# 如果 b 大于 1 返回 面积大于1
return u'面积大于1'
# 条件不成立
else:
# 返回 面积小于或等于1
return u'面积小于或等于1'
其实还有一种简写的方法,直接在表达式内输入以下,也可实现单一条件判断:
u'面积大于1' if !mj! > 1 else u'面积小于或等于1'
思考:如果不用条件判断的方法,使用其他的工具配合,是否可以实现示例中的效果?
当然,也可以有多条件判断。但如果
在使用arcgis的过程中,你是否有发现在 shp文件 和 要素类的属性表中,总会存在一个名为“Shape”的字段,而且该字段不可以编辑或者删除。
其实这个字段不是如显示的一样,存储的是(点、线、面)的文字,属性表中“Shape”字段储存的是该条属性对应图形的属性信息。并且属性可以通过字段计算进行调用(不可修改)。调用表达式如下(python):
坐标获取:
# 获取要素重心点坐标(点要素不可使用)
!shape.trueCentroid.X! # 重心点x
!shape.trueCentroid.Y! # 重心点y
# 获取坐标(图形外接矩形4角坐标)
!shape.extent.XMax! # 最大x
!shape.extent.XMin! # 最小x
!shape.extent.YMax! # 最大y
!shape.extent.YMin! # 最小y
# 点要素 x y z 获取
!shape.X!
!shape.Y!
!shape.Z!
面积、周长获取:(再也不用“计算几何”了。笑)
# 计算面积(单位与要素坐标系一致)
!shape.area!
# 计算椭球面积
!shape.geodesicArea!
# 计算周长(长度)
!shape.length!
杂项:(可以进行简单的质检)
# 判断要素是否为多部件(布尔值)(可判断空洞)
!shape.isMultipart!
# 获取要素部件数量(要素内有空洞仍记为1,无法区分空洞)
!shape.PartCount!
# 获取要素的折点数量
!shape.pointcount!
案例说明:下图中,省与市的名称长度均不固定(行政区名称均已省或市结尾,不考虑特殊情况),分别提取省、市的名称。
案例分析:调查机构(DCJG)字段内填写的文字结构为某省某市,可以通过(index)找到“省”字所在位置,向前与向后提取文字。
python表达式:
# 提取省的名称:
!DCJG![:!DCJG!.index(u"省") + 1]
# 提取市的名称:
!DCJG![!DCJG!.index(u"省") + 1:]
解释:
@ 在 "省" 前面加 u 的原因:因为argis储存字符串是以 utf-8 的格式进行存储,且arcmap 的python版本为 2.7,在使用方法或函数处理汉字时,需要在前面加一个 u 表示字符串为utf-8编码
arcgis pro 不需要加
@ !DCJG!.index(u"省") 会返回“省”这个字符,在字段 !DCJG! 中的位置。
@ 通过 !DCJG![位置 : ] 或 !DCJG![ : 位置] 的方式提取前后的文本
那么,问题来了,为什么需要“位置+1”呢?提取省和提取市的“位置+1”原因是否一样?(1.3中有讲到)
案例说明:数据来源字段如下图,要求提取其中的数值,并将其填入双精度字段。
案例分析:因为此类情况比较复杂,面积数值是不固定的,且数值前、后的字符数量也不固定,本文介绍的其他方法无法解决此情况。此类情况可采用正则表达式来对字符进行提取。
由于在python中使用正则表达式,需要引入 re 模块,所以得使用 代码块来配合实现。
代码块与代码说明:
# 引入 re 模块
import re
# 定义函数,名为 aa , 变量为 in_str
def aa(in_str):
# 使用正则表达式 按规则进行提取
mj_str = re.search(r'\d*\.\d*', in_str).group()
# 由于被计算字段类型为双精度,所以将正则表达式提取的str类型的面积 转为 float 类型
mj_float = float(mj_str)
# 返回面积
return mj_float
正则表达式太深奥,再这里仅作介绍,如有需要可自行查询。
(代码可直接使用,且比较通用,但仍建议会一点点python再观看本节)
如下如,现有 要素A 和 表B ,通过计算 表B 的 MJ 字段,汇总 要素A的地类名称等于 表B 中DL 字段的 图斑面积之和。
其实这个目标,可以使用工具实现(那么,需要使用哪些工具呢?笑),本小节仅对字段计算实现的另一种方式进行探讨。
实现方式:通过使用arcpy游标遍历 要素A,汇总面积,并将结果通过 global 在自定义函数内调用。维护 表B 的 MJ 字段。
表达式:
aa(!DL!)
代码块:
# 引入 arcpy 模块
import arcpy
# 定义 要素A 的路径(自定义部分)
fc_A = u'C:\\ArcGIS\\Default.gdb\\A'
# 定义储存面积的字典
mj_dict = {}
# 查询游标 遍历 要素A
cursor = arcpy.SearchCursor(fc_A)
for row in cursor:
dlmc = row.getValue('DLMC') # 获取地类名称(分组字段-自定义部分)
tbmj = row.getValue('TBMJ') # 获取面积(汇总字段-自定义部分)
if dlmc not in mj_dict.keys(): # 字典维护
mj_dict[dlmc] = 0
mj_dict[dlmc] += tbmj # 字典维护
# 自定义函数, 变量 a 用于储存 表2 中的 "DL"字段值
def aa(a):
global mj_dict # 引入全局变量
if a in mj_dict.keys():
return mj_dict[a] # 维护值
else:
return 0 # 如果不存在,返回 0
使用arcgis工具实现的话,可以先用“汇总统计数据”按地类名称分组汇总面积。然后再将结果与表B,通过匹配“地类名称和DL”字段进行“连接字段”。
部分数据类型无法实现,在计算字段时,值字段内包含被计算字段(有点绕)。示例如下:
@数据情况:有两个字段,一个是类型,一个是编号。
@目的:只使用1次字段计算器,将类型和编号字段的拼接值填写入编号字段。
Python:
!类型! + !编号!
@此时,计算字段既要从编号字段提取值,又要向编号字段内填写值。
若使用pythohn解析程序计算时需要用到这种方法,请注意mdb(个人地理数据库)内所有类型的要素或表格,均无法使用此方法。VB解析程序无此情况。