ArcPy学习笔记(三)处理空间数据

第三章 处理空间数据

1.使用游标访问数据
游标是一个数据库术语,主要用于访问表格中的每一行记录或者向表中插入新的记录。在表格中,一条记录也被称为一行。游标通常用于从表格中按行读取或写入新几何结构。
游标有三种形式:搜索、插入、更新
在这里插入图片描述
上图为官网的描述,有关游标的具体内容可见
https://desktop.arcgis.com/zh-cn/arcmap/10.3/analyze/python/data-access-using-cursors.htm
游标只能向前导航,因此若脚本想要多次遍历,就必须重新执行游标。所以需要for循环或while循环来配合游标使用。
通过游标搜索到的记录会输出到一个字段列表中,列表内字段值的顺序和函数中field_name参数内字段值的顺序保持一致
下面是一个使用游标遍历记录的例子。该例中,遍历了GBA.shp中的类型字段

#-*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import arcpy
fc="D:/PythonforArcGIS/study/shapefile/GBA/GBA.shp"
cursor = arcpy.da.SearchCursor(fc,["类型"])
for row in cursor:
    print "类型={0}".format(row[0])

值得注意的是,Python2.7版本对于中文输出存在编码不同的问题,如果字段或列表中有中文,需要在代码最前面加上前4行代码。
输出结果为
在这里插入图片描述
原属性表为
在这里插入图片描述
当然,可以进一步改进上述代码,使用with语句后,无论游标成功运行还是报错都可保证数据库锁的关闭与释放,并重置迭代。代码如下:

#-*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import arcpy
fc="D:/PythonforArcGIS/study/shapefile/GBA/GBA.shp"
with arcpy.da.SearchCursor(fc,["类型"]) as cursor:
	for row in cursor:print "类型={0}".format(row[0])

注意这段代码,在使用with语句后的for循环下的print语句不能换行,如果换行就会报错。

下面将演示在某一字段下插入一个新行:

#-*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import arcpy
fc="D:/PythonforArcGIS/study/shapefile/GBA/GBA.shp"
#先把游标移到目标的字段位置
cursor=arcpy.da.InsertCursor(fc,["类型"])
#在该字段里插入新行
cursor.insertRow(["县级市"])

输出结果如图
在这里插入图片描述
可以发现在多了一行数据,并在“类型”字段下多了一个“县级市”

也可以通过循环来插入多行数据:

#-*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import arcpy
fc="D:/PythonforArcGIS/study/shapefile/GBA/GBA.shp"
cursor=arcpy.da.InsertCursor(fc,["类型"])
x=1
while x <= 5:
    cursor.insertRow(["直辖市"])
    x+=1

运行结果如图
在这里插入图片描述

下面代码将演示如何删除一行数据

#-*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import arcpy

fc="D:/PythonforArcGIS/study/shapefile/GBA/GBA.shp"
with arcpy.da.UpdateCursor(fc,["类型"]) as cursor:
    for row in cursor:
        if row[0]=="直辖市":
            cursor.deleteRow()

输出结果如下
在这里插入图片描述
可以发现之前添加的“直辖市”的内容被删除了。

插入游标和更新游标均支持编辑操作。在ArcGIS地理处理框架中,创建游标对象的同时会在属性表上添加一个锁。这个锁能防止多个进程同时更改一个属性表。
锁有两种类型:共享锁与排它锁。
当访问表格或数据集时会应用共享锁;同一属性表中允许存在多个共享锁,但存在共享锁时将不允许存在排它锁。
当对属性表或要素类进行更改会应用排它锁;在使用游标或更新游标时都会在数据集上应用排它锁。

而在应用程序或脚本释放数据集(通过关闭或明确释放游标对象)之前,锁将一直存在。在脚本中可以使用del语句删除游标对象,否则,将会阻止所有其他程序或脚本访问该数据集。而在一个创建了插入游标或更新游标的脚本中,需要用两个del语句,一个删除行对象(del row),一个删除游标对象(del cursor)
注意:在使用with语句后可以保证数据库锁的关闭与释放,因此不需要再使用del语句。

2.在Python中使用SQL语句
通过SearchCursor函数可执行SQL查询语句,语法如下
在这里插入图片描述
其中可选参数where_clause表示一个SQL表达式。查询不同的数据集,where_clause参数中的SQL语句会存在细微差别,但都遵循SQL语法规则。

import arcpy
fc="D:/PythonforArcGIS/study/shapefile/GBA/GBA.shp"
with arcpy.da.SearchCursor(fc,["Name","Classcode"],'"Classcode"=1') as cursor:
    for row in cursor:
        print row[0]

上述代码仅为示意。

因为SQL针对不同格式的要素有不同的语法,所以可以使用AddFieldDelimiters函数,语法如下
AddFieldDelimiters(database,field)
演示如下:

#-*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import arcpy
fc="D:/PythonforArcGIS/study/shapefile/GBA/GBA.shp"
fieldname ="类型"
delimfied=arcpy.AddFieldDelimiters(fc,fieldname)
cursor=arcpy.da.SearchCursor(fc,["市","市代码"],delimfied+"='地级市'")
for row in cursor:
    print "{} {}".format(row[0],row[1])
del row
del cursor

这样就可以输出,类型是“地级市”的城市名称和城市代码,结果如下:
在这里插入图片描述
此外,这种SQL语句也广泛的应用于很多工具中,如select工具,其语法如下

Select_analysis (in_features, out_feature_class, {where_clause})

和SearchCursor一样,where_clause在这里就是一个SQL语句。

3.处理表和字段名
ValidateTableName函数可以用来确定某个表名在给定的工作空间中是否有效,函数语法:
ValidateTableName(name,(workspace))
函数参数是一个表名和一个工作空间路径,函数将为该工作空间返回一个有效的表名。如果表名有效则返回原始表名;如果表名无效。则其中的无效字符均用_下划线代替。

import arcpy
tablename=arcpy.ValidateTableName("Panyu","D:/PythonforArcGIS/study/shapefile/GBA")
print tablename

输出结果为
在这里插入图片描述
在这里Panyu是一个shp文件,能输出说明这个表名可以是数据集的名称。

下面这个例子将演示:使用CopyFeatures工具将shp从文件夹转移到另一个文件夹中。其思路为,先通过basement属性将.shp文件扩展名从文件名中移除,随后验证文件名,并将shp拷贝到另一个地理数据库中。

import arcpy
import os
from arcpy import env

env.workspace="D:\\PythonforArcGIS\\study\\shapefile\\GBA"
outworkspace="D:\\PythonforArcGIS\\study\\shapefile\\GBA2.gdb"
fclist=arcpy.ListFeatureClasses()
for shapefile in fclist:
    fcname=arcpy.Describe(shapefile).basename
    #先把文件名都保存到newfcname中
    newfcname=arcpy.ValidateTableName(fcname)
    #再通过path.join函数将新获取的文件名拼接到新文件夹的路径后面
    outfc=os.path.join(outworkspace,newfcname)
    #使用复制工具将shp文件转移到新文件夹中
    arcpy.CopyFeatures_management(shapefile,outfc)

思路如上述代码所示,但无法输出,需要随后再调试

另外,可以将ValidateFieldName函数作为一个判断语句,只有当字段名有效情况下才能添加字段。下面这段代码将验证新字段名称的有效性,并通过AddField工具将有效字段添加到数据中。

import arcpy
fc="D:/PythonforArcGIS/study/shapefile/GBA/GBA.shp"
fieldname=arcpy.ValidateTableName("NEW")
arcpy.AddField_management(fc,fieldname,"TEXT","","",12)

输出结果如图所示
在这里插入图片描述
类似于ValidateTableName函数,ValidateFieldName函数也不会判断字段名是否存在,因此脚本仍然会报错,或覆盖一个已经存在的字段。
确定表名是否存在可以使用CreateUniqueName函数。使用方式为

import arcpy
from arcpy import env
env.workspace="D:/PythonforArcGIS/study/shapefile/GBA"
unique=arcpy.CreateUniqueName("GBA.shp")
arcpy.Buffer_analysis("GBA.shp",unique,"100 FEET")

因为工作空间中已有GBA,因此第一次运行输出GBA0.shp
在这里插入图片描述
同理,第二次运行将输出GBA2.shp

4.解析属性表和字段名
ArcGIS中的地理环境经常需要设置成要素或属性表的全限定名。而有时在处理过程中不光要知道要素的名称,还需要知道要素的路径,数据库名称以及数据的所有者。
ParseTableName函数可以将数据集中的全限定名称分割成不同的组成部分。语法如下
ParseTableName(name,(workspace))
ParseTableName返回一个由逗号隔开,并含有数据库名、所有者名以及表明的字符串。演示如下:

import arcpy
from arcpy import env
env.workspace="D:/PythonforArcGIS/study/shapefile/GBA"
fc="Panyu"
fullname=arcpy.ParseTableName(fc)
namelist=fullname.split(",")
databasename=namelist[0]
ownername=namelist[1]
fcname=namelist[2]
print databasename
print ownername
print fcname

输出结果如下,因为Panyu数据经过处理,所以没有保存数据库名、所有者名,只能输出null。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/c6983127/article/details/107737896