一、完整代码
实例:已知河流流向,且将河流转成栅格再转成点,点含有HYRIV、NEXT、DEM属性,分别代表目前所属河流的ID、流向下一河流的ID、高程值。现在需要根据河流流向计算高程差,思路是同一河流内的点直接进行下一点减去当前点的DEM;河流最后一个点则根据NEXT属性寻找下一河流的第一个点,并计算高程差。
关键点:跨行计算实际还是先提取出属性字段值,然后保存在列表中计算,再通过Update给字段赋值。
import arcpy
from arcpy import env
env.workspace = "F:/test"
sort_in = "DEMpt.shp"
sort_out = "result.shp"
# 点按照HYRIV进行排序
arcpy.Sort_management(sort_in, sort_out, [["HYRIV", "ASCENDING"]])
# 创建保存高程差的字段D
arcpy.management.AddField(sort_out, "D", "LONG")
# 创建列表Dlt(保存高程差) ; Flt(标记河流第一个点)
HYRIVlt = []
NEXTlt = []
DEMlt = []
Dlt = []
Flt = []
# 提取字段 'HYRIV', 'NEXT', 'dem' 并保存在列表中
fields = ['HYRIV', 'NEXT', 'RASTERVALU']
# 使用游标遍历行
shprows = arcpy.SearchCursor(sort_out, fields)
# 使用While进行迭代搜索游标,通过游标的next返回下一行
while True:
shprow = shprows.next()
if not shprow:
break
# 空列表不能通过索引添加值,需要使用append的方法进行赋值。
# 这里需要注意需要使用已有的shp文件,不能是程序运行生成的sort_out.否则提示shprow没有该属性
DEMlt.append(shprow.RASTERVALU)
HYRIVlt.append(shprow.HYRIV)
NEXTlt.append(shprow.NEXT)
# 给第一个点赋值
Flt.append(HYRIVlt[0])
Dlt.append(DEMlt[1] - DEMlt[0])
# 通过列表计算高程差
for i in range(1, len(HYRIVlt)-1):
if HYRIVlt[i] == HYRIVlt[i+1]: # 如果是同一河流内的点
Dlt.append(DEMlt[i+1] - DEMlt[i])
Flt.append(0)
elif HYRIVlt[i] != HYRIVlt[i+1]: # 如果是同一河流最后一个点
Dlt.append(9999)
Flt.append(0)
elif HYRIVlt[i] != HYRIVlt[i-1]: # 如果是同一河流的第一个点,则标记其序号给Flt
Flt.append(HYRIVlt[i])
# 最后一个点赋值
Flt.append(0)
Dlt.append(9999)
# 找到河流最后一个点,并通过NEXT值与Flt的索引找到河流流向的第一个点。
for j in range(1, len(HYRIVlt)):
if Dlt[j] == 9999:
nextpt_index = Flt.index(NEXTlt[j]) if NEXTlt[j] in Flt else -1
if nextpt_index != -1:
Dlt[j] = DEMlt[nextpt_index] - DEMlt[j]
# 如果找不到河流流向的下一个点
else:
Dlt[j] = Dlt[j-1]
n = 0
# 通过列表给字段赋值
with arcpy.da.UpdateCursor(sort_out, ['D']) as cursor:
for row in cursor:
result = Dlt[n]
row[0] = result
n += 1
cursor.updateRow(row)
del row, cursor
二、其他问题
(1)更新游标时报错“TypeError: 'Row' object does not support item assignment”
arcpy.da.UpdateCursor 与arcpy.UpdateCursor 的赋值方式不一样,前者可以直接用“=” 赋值,后者需要通过setValue()方法给行赋值。
同样需要注意Data Class模块中的其他类与arcpy下的游标函数的区别,Data Class模块下的游标类是在ArcGIS 10.1中引入的,可以直接通过下标获取或者设定当前行的值,比如row[0]=1;而arcpy下的游标函数需要运用setValue()、getValue(),如row.setValue("distance", 100)、row.getValue("name")
三、参考
(1)跨行计算
[1] (31条消息) python/arcpy提取shp文件属性表中的字段值_arcpy 获取字段值_A-Chin的博客-CSDN博客
[2] (31条消息) arcpy读取featureClass中某一字段的所有属性值,存放到list中(地理国情监测)_木易GIS的博客-CSDN博客
[3] (32条消息) Python(arcpy) 批量读取点元素文件(shp)属性表的字段_arcpy读取属性表_天外来客Jonty的博客-CSDN博客
[4] ArcPy cursor get value in next row - Geographic Information Systems Stack Exchange (这个还提到在地理数据库下与文件夹下两者运用的区别)
(2)索引
[1] (31条消息) python列表中查找某个元素的索引_python 列表查找索引_fff2zrx的博客-CSDN博客
[2] 在python中处理list.index(可能不存在)的最好方法? - 问答 - 腾讯云开发者社区-腾讯云 (tencent.com)
(3)游标函数区别