================2018.4.8 更新==============
最近在搞事情时发现ArcMap里的【空间连接】工具可以实现根据图层间的空间关系进行属性的连接,关于空间连接的详细内容可以参考官网的帮助文档;
如下图所示,利用点数据分别与村、镇的面数据进行空间连接,即可根据空间关系把村镇的属性赋值给点数据。村镇面属性表进行点与村空间连接
点与村空间连接的成果再与镇进行空间连接两次空间连接后属性表的效果
从两次连接后的点数据属性表可以看到村镇的属性已经赋值给点数据了,然后利用字段计算器即可进行相关的操作完成对应的需求;
===========================2018.4.8 更新========
这里先说一下上一篇文章最后留下的那个问题:把点坐标文档里的点的顺序打乱了,最后能不能生成面?去尝试了一下,结果是不行的,说明Arcpy中点构面也有一定的顺序的,所以随便不能搞混点的位置。搞混点顺序生成的面如图1所示 是一个不能生成完整的面。图1
上周六早上还在梦乡的我被一个信息吵醒,睁开朦胧的眼睛起来一看,居然是小仙女 向我寻求帮助,说工作很急很急!她正在弄地名普查的数据检查工作,叫我帮她弄一个程序;虽然很困,但是想到对面的小仙女那么着急,有点不忍心拒绝,然后我二话不说打开电脑,来不及洗漱,饿着肚子在电脑面前撸起了代码……经过一个多小时的努力,终于基本完成了小仙女的需求,然后迫不及待的把代码发给小仙女,怀着期待的心情,等待着小仙女的回复,等来的却是:“我已经弄完了!”这时我的心情是多么的……
现在有空总结一下上周六尴尬的事情,一个简单的小程序居然弄了一个多小时,确实有点慢,那么菜,还得继续好好修炼啊。那么慢的另一个原因就是对小仙女的需求了解不够,手上也没调试的数据,对那个数据表的结构不清楚等等,这些都要边敲代码边去询问;另外,当时太过于兴奋,没有把思路弄清楚就去盲目敲代码,导致后面的代码要改来改去。所以要吸取经验教训,凡事都要先弄清楚需求,需求是我们的工作的方向标,需求清楚后再去把思路弄清楚,最后才是通过代码去实现需求。
之后小仙女也跟我分享了他们的解决方法,他们是用 属性表关联+字段运算 完成的;那时就像发现了新大陆,原理属性表关联还有那么厉害的功能。反正条条大路通罗马,解决问题的办法不止一种,适合自己的才是最好的方法。属性表关联的详细过程到时可以参考小仙女的分享。
下面我就说说我的解决方案吧!
言归正传,先说说小仙女的需求:三个图层(地名点,镇区面,村域面)和一个地名Excle表格;先在Excel表格里找出重复的地名,然后在地名点图层找到该重复的地名点,补充完整这些地名点的属性表信息,其中镇名字段就是地名点所在镇区的名字,村名字段就是地名点所在村的名字,最后把该地名名称改为:村名+地名。
获得Excel表格中重复的地名
python操作excel表格需要先安装第三方类库xlrd,xlrd库只能操作97-2003版本的(.xls)(经过后面的实验验证,xlrd可以同时操作.xls或者.xlsx版本的表格);然后就可以调用该类库的函数去操作Excel,获得我们需要的信息。地名都位于第一列,所以读取相对简单点(如图2)图2 地名表
代码如下:
#coding=utf-8
import xlrd
import arcpy
def getpointNameList(Exclepath):
PointNameList=[]
#excle表格格式要为.xls
data=xlrd.open_workbook(Exclepath) #打开excle表格
table=data.sheets()[0] #获得Excel里的第一张表
nameList=table.col_values(0) #获得第一列(地名),为列表格式
#在nameList中查找查找重复的点名
for name in nameList:
if nameList.count(name)>1:
PointNameList.append(name) #获得的是所有重复值
PointNameList = list(set(PointNameList)) #在重复值列表中去重
return PointNameList
完善点图层的属性信息
因为我手上也没有调试数据,所以根据小仙女的需求,简单的构建了测试数据需要的字段,数据的属性表如下图3,4,5,6图3 测试数据图4 地名点图层属性表图 5 村域图层属性表图 6 镇区属性表
字段名称,表格名称尽量不要用中文吧,因为python2对中文兼容性不好,刚刚开始我用中文是也报错了
利用getpointNameList()函数的返回值在点图层里找到对应的点,然后分别利用该点去与镇区、村域图层进行位置关系的判断(这里是利用contains函数),如果点在面中,就获取镇名,村名写入到点图层属性表相应的字段中,最后更改地名点的名称。
def WriteAttribute(PointNameList,pointpath,zhenpath):
for name in PointNameList: #遍历地名列表
pointCursor = arcpy.UpdateCursor(pointpath) # 点数据更新游标
for pointrow in pointCursor:
pointGeo=pointrow.shape #获得点的几何图形
if pointrow.PointName==name: #判断点名是否相等
zhenCursor = arcpy.SearchCursor(zhenpath) # 镇区的搜索游标
for zhenrow in zhenCursor: #循环判断点是否在面中
zhenGeo=zhenrow.shape
if(zhenGeo.contains(pointGeo)):
pointrow.zhenName=zhenrow.zhenName #如果在面中,获得该面的镇名并填入点属性表中
cunCursor = arcpy.SearchCursor(cunpath)
for cunrow in cunCursor:
cunGeo = cunrow.shape
if (cunGeo.contains(pointGeo)):
pointrow.cunName = cunrow.cunName
pointrow.PointName = cunrow.cunName + name
pointCursor.updateRow(pointrow)
存入相应的参数,调用上面两个函数,就基本完成了小仙女提出的需求了。
程序运行后的结果如图7所示。对比图4的表,我们可以看到PointName,zhenName,cunName这三个字段已经更新了。至于有些地名点没有更新,是因为我在构建Excel表格时故意没有让它重复,所以它就被排除在外,不用更新了。更新后的属性表
总结:
最后自己调试才发现自己上周六写的程序错漏百出,是多么的烂,幸好那天小仙女没有把希望都寄托在我的烂程序上,要不然就尴尬了。技术不过关,还是不要去丢人现眼了,好好修炼。
这篇文章中用到的函数功能前面的文章都有涉及,无非就是三个游标的使用,几何图形的空间位置的判断等。加入一个新的内容就是xlrd类库的应用,对于这个类库的详细使用这里就不再阐述,网上有很多相关的教程,仔细去看还是可以看懂的。
据我了解现在GIS行业比较多的项目都是地名普查,不动产登记,土地确权,三调等数据量比较大的项目,所以对于数据批处理的需求也很大。所以觉得python在当中将会发挥着巨大的作用,因为python有丰富的第三方类库,几乎需要什么功能你都能找到对应的类库,然后去调用简单的函数就能实现你需要的功能,这样对于数据处理帮助很大。比如说这里的xlrd。
专栏文章会同步到微信公众号【GIS学习交流】
欢迎大家关注公众号一起交流,一起学习,一起进步!