8 处理空间数据与表格数据(2)

8.5 解析表与字段名

ArcGIS Pro 地理处理环境始终使用要素类和表的完全限定名称。例如,要处理名为道路的要素类,地理处理工具不仅必须知道名称,还必须知道路径、数据库名称和数据所有者。在使用地理数据库时,此信息是必不可少的。将数据集的完全限定名称拆分为其组件通常称为解析arcpy.ParseTableName() 函数可用于此任务。这个函数的语法是:
arcpy.ParseTableName(name, {workspace})
ParseTableName 函数返回包含数据库名称、所有者名称和表名称的单个字符串,每个字符串用逗号分隔。例如,以下代码对要素类列表使用 ParseTableName() 函数来获取完全限定名称的组件,然后将这些组件拆分为列表:

import arcpy
arcpy.env.workspace = "C:/Data/study.gdb"
fcs = arcpy.ListFeatureClasses()
for fc in fcs:
    fullname = arcpy.ParseTableName(fc)
    namelist = fullname.split(", ")
    databasename = namelist[0]
    ownername = namelist[1]
    fcname = namelist[2]
    print(databasename)
    print(ownername)
    print(fcname)

类似的方法可用于使用 arcpy.ParseFieldName() 函数将表中字段的完全限定名称拆分为其组件。此函数返回一个包含数据库名称、所有者名称、表名称和字段名称的字符串,每个字符串用逗号分隔。
注意:也可以使用 Python 中的内置解析函数进行解析。但是,Python 中的解析函数采用特定的语法,可能会因不同的数据集而改变。例如,每种类型的地理数据库(文件、企业)的解析语法都不同。 ArcPy 解析函数专门设计用于处理地理数据库,因此更加健壮。

8.6 python 字段计算

除了使用 ArcPy 为地理处理和其他工作流等任务编写脚本外,Python 还用于 ArcGIS Pro 的其他部分。一些工具使用 Python 编写表达式作为工具参数之一。这些工具包括Calculate Field, Calculate Fields, Calculate Value.
注意:计算值工具是仅限模型构建器的工具。它基于 Python 表达式返回一个值,但它不适合在 Python 脚本中使用。

考虑计算field 工具的示例,它是典型 GIS 工作流中使用最广泛的工具之一。
在这里插入图片描述
计算字段工具用于计算表中字段的值。它可以由每个记录都相同的单个值组成,也可以基于其他字段中的值,包括几个不同的运算符。在这种情况下,“计算”不仅仅包括对数值的操作,还包括其他数据类型,例如字符串、日期和几何。

计算字段工具支持三种类型的表达式:Python 3、Arcade 和 SQL。 Python 3 是默认的,也是使用最广泛的。 Arcade 是 Esri 专门编写的用于 ArcGIS 平台的表达式语言。 Arcade 具有与 Python 和 JavaScript 等其他脚本语言相同的一些功能,但它的安全漏洞较少。由于与通用脚本语言相比,Arcade 用于少量特定任务,因此也相对简单。本节末尾包含一个在 Python 脚本中使用 Arcade 表达式的示例。 SQL 表达式仅受 ArcGIS Online 中托管的要素服务支持,此处不予讨论。

注意:Python 3 表达式类型不是指 Python 版本 3,而只是指这是 ArcGIS Pro 中 Python 表达式类型的第三个版本(在早期版本中称为 Python 和 Python _9.3 的表达式类型之后)。 Esri 软件)。 Python 3 遵循常规 Python 语法,但由于代码在特定上下文中使用,因此需要进行一些修改,如以下示例中所述。另请注意,与 SQL 查询中使用的 WHERE 子句相比,此上下文中的 SQL 表达式使用 SQL 语言的不同子集。
使用计算字段工具时,要计算的字段需要存在,并覆盖现有值

表达式的最简单示例是为每条记录输入相同的值。例如,要将字符串写入字段,表达式由 Python 字符串组成:\

TEXTFIELD = "Sample text"

双引号和单引号都可以使用。不带引号的字符串会导致错误。
完成的工具对话框如图所示。
在这里插入图片描述
这里的操作很容易明白,大多数人都在arcmap或者arcgis pro 中进行过相同的操作。

要将数字写入字段,表达式由整数或浮点数组成:

NUMFIELD = 123.456

字段的数据类型很重要,因为它决定了哪些值是有效的。例如,TEXT 字段可以同时包含字符串和数字(​​作为字符串),但数字字段(SHORT、LONG、FLOAT、DOUBLE)不能包含字符串。了解数据类型是相关的,因为计算字段工具的内置验证不考虑字段的数据类型。当您单击验证图标(绿色复选标记)时,将验证表达式而不考虑字段的数据类型。因此,表达式可能是有效的(即使用正确的 Python 语法),但由于数据类型没有意义,该工具会导致错误。例如,考虑将字符串写入数字字段:

NUMFIELD = "TEST"

Failed on input OID 1, could not write value 'TEST' to output field NUMFIELD.

许多表达式不是每条记录都包含相同的值,而是使用其他字段的值。例如,您可以**复制现有字段的值而不进行任何更改。表中的字段必须使用用感叹号包围的字段名称来引用,**如下所示:

TEXTFIELD = !CODE!

该表达式将 CODE 字段的值复制到工具中选择的字段,即 TEXTFIELD。
感叹号的使用需要一点时间来适应,因为在这些表达式中**引用字段的方式是独一无二的。**您正在编写 Python 代码,但要使代码使用现有字段,您必须使用感叹号。此语法在常规 Python IDE 中不起作用。
注意:这些表达式中的字段名称不区分大小写,因此您可以使用 !Code!或!code!而不是仅仅 !CODE!。

您可以使用运算符执行计算。考虑一个名为 ACRES 的字段,它使用 Shape_Area 字段中的值(以平方英尺为单位)进行计算。转换计算如下:

ACRES = !Shape_Area! / 43560

可以使用所有常规 Python 运算符,包括加法 (+)、减法 (-)、乘法 (*)、除法 (/)、下除法 (//)、模 (%) 和指数 (**)。您可以添加空格以提高可读性,但空格不会影响表达式。除了使用感叹号来引用现有的字段名称外,常规的 Python 语法都适用。
使用字符串时,您可以使用字符串方法来操作值。字符串方法使用 Python 的常规 . 点表示法,其中对象是引用字段。例如,以下代码在引用字段中创建值的小写字符串:

TEXTFIELD = !CODE!.lower()

也可以使用索引和切片。以下示例仅复制现有字符串的前三个字符:

TEXTFIELD = !CODE![:3]

您还可以使用 Python 的几个内置函数,包括 max()、min()、round() 和 sum()。以下示例从字段列表中计算最大值:

max([!NUM1!, !NUM2!, !NUM3!])

Python 的内置模块可以直接使用,包括数学。考虑一个名为 VALUE 的现有字段,其数字必须经过对数转换或转换为其对数值,并且必须将新数字写入名为 LOG_VALUE 的字段:

LOG_VALUE = math.log(!VALUE!)

Python 的许多其他内置模块对于创建表达式很有用,包括 datetime、random、time 等。无需像在脚本中那样首先导入这些模块以在表达式中使用它们。
除了使用表中现有字段的值之外,您还可以使用几何对象的属性。这类似于在使用游标时使用 SHAPE@ 标记,如第 9 章中更详细说明的那样。例如,以下表达式使用 area 属性将每个特征的面积写入名为 AREA 的字段:

AREA = !Shape.area!

请注意,此版本与早期的 !Shape_Area! 不同,后者引用了一个名为 Shape_Area 的字段,该字段是任何多边形地理数据库要素类的字段的一部分。前面的表达式通过 Shape 字段引用几何对象,然后使用 area 属性。
单位转换是内置的,很方便。以下代码将面积直接计算为英亩:

ACRES = !Shape.area@acres!

其他属性包括 type、extent、centroid、firstPoint、lastPoint、length、isMultipart 和 partCount。例如,以下表达式确定每个特征的零件数,并将此数字写入名为 PCOUNT 的字段:

PCOUNT = !Shape.partCount!

许多典型的表达式可以写成一行代码。可以使用代码块构建更复杂的表达式。此功能允许您在 Python 中编写自定义函数来执行更精细的计算。
以下示例说明了如何编写此类函数。表达式调用函数并传递参数。在以下示例中,自定义函数称为 m2_to_ft2,参数是浮点数形式的特征面积(以平方米为单位)。该函数将面积从平方米转换为平方英尺。

Area_SQFT = m2_to_ft2((!Shape.area!)

此函数需要使用math模块:

import math

自定义函数在代码块中定义,使用 def 关键字后跟函数名称和括号中的参数(如果有)。在这种情况下,参数是特征的区域。
在以下示例中,此变量称为“区域”,但也可以称为其他名称:

def m2_to_ft2(area):

def 语句的代码行以冒号结尾,后面是缩进的代码块,用于执行函数本身。在此示例中,以平方米为单位的面积转换为平方英尺。该值必须使用 return 语句从函数返回,如下所示:

        return math.pow(3.2808, 2) * area

在这里插入图片描述
也可以使用单行表达式来确定以平方英尺为单位的面积,但该示例说明了代码块的工作原理。
下面是一个更详细的示例,它使用现有文本字段的值来分配数字代码。
这类似于栅格中的重新分类,但现在应用于表的值。在示例中,使用 if-else 结构为唯一的土地利用类别分配了一个整数值。该表达式引用包含描述性类别的现有 LU_TXT 文本字段,并将数值写入 LU_NUM 字段。表达式是

LU_NUM = reclass(!LU_TXT!)
def reclass(landuse):
    if (landuse == "GOVERNMENT"):
        return 1
    elif (landuse == "INSTITUTIONAL"):
        return 2
    else:
        return 3

在大多数情况下,在表达式或代码块中运行代码会产生相同的结果。一个例外是使用随机数时。考虑使用 Python 代码创建 0 到 100 之间的随机数:

random.random() * 100

虽然这段代码产生了一个随机数,但每条记录的结果都是相同的,因为 random 模块的 random() 函数只被调用一次。如何为每条记录获取不同的随机数?这需要一个自定义函数。表达式是

RAND100 = rand()
import random
def rand():
    return random.random() * 1000

代码看起来相同,但通过使用自定义函数,会为表中的每条记录调用 random() 函数。
这些代码块可以变得复杂。您可以将代码导出为 .cal 文件,以后可以再次导入这些 .cal 文件。 .cal 文件是一个文本文件,其中包含为导入而格式化的表达式和代码块的内容。虽然 .cal 文件不是 Python 脚本文件,但您可以将其作为文本文件打开并使用 Python 代码。
前面的示例已经说明您可以在表达式中使用几何对象。您不仅可以读取属性,还可以修改它们。以下示例说明如何使用代码块将点要素的 x 坐标移动一定距离。
要使用几何对象,字段名称必须设置为 Shape 字段。此语法类似于使用 SHAPE@ 设置游标。表达式调用自定义函数:

Shape = shift(!Shape!)

注意:提醒一下,这些表达式中的字段名称不区分大小写,因此您可以使用 !shape!、!Shape! 或 !SHAPE!。
代码块定义了一个自定义函数,它将 x 坐标移动 25 个单位(坐标系):

def shift(shape):
    point = shape.getPart(0)
    point.X += 25
    return point

这段代码需要一些解释。首先,使用了 Shape 字段,这意味着实际的几何对象,而不仅仅是一个属性,被引用。需要参考几何对象,因为正在修改要素的几何。其次,将几何对象传递给函数。第三,理论上,特征可以由多个部分组成,因此 getPart() 方法与索引零 (0) 一起使用以获取几何的第一(也是唯一)部分,即一个点。最后将点特征的x坐标平移,返回新的点。
因为计算字段工具会更改数据,所以对几何的编辑会以与属性值类似的方式写入要素类。
这个代码块比较复杂,同样的任务可以用游标来完成。第 9 章更深入地讲解使用游标读取和写入几何图形。
在工具对话框的 Helpers 部分下的 Calculate Field 工具中内置了一些有助于编写表达式和代码块的有用元素。**本节列出了常用的代码元素,例如数学模块的函数(例如,math.log())和字符串对象的方法(例如,lower())。**还有一些元素可以帮助编写代码块,包括 if-else、for、while 等,以及用于常见任务的模板。例如,有一个代码块模板来创建一个序号。表达式调用自定义函数,如下:

NEWID = SequentialNumber()
rec = 0
def SequentialNumber():
    global rec
    pStart = 1
    pInterval = 1
    if (rec == 0):
        rec = pStart
    else:
        rec = rec + pInterval
    return rec

该代码使用 global 关键字,这使得修改当前范围之外的变量成为可能。通过将变量rec定义为函数内部的全局变量,该变量可以在函数外部使用。
注意:示例代码不使用 Python 样式指南中建议的全小写变量名称样式。但是,由于代码直接取自计算字段工具中的示例,因此代码保持不变。

其他示例可在 ArcGIS Pro 帮助页面中的“计算字段 Python 示例”主题下找到。到目前为止的示例已经展示了如何在计算字段工具的工具对话框中编写 Python 表达式。因为这是一个常规的地理处理工具,所以它也是 ArcPy 中的一个功能。该工具的语法如下:

CalculateField(in_table, field, expression, {expression_type}, 
               {code_block})

语法不完全遵循工具对话框的设计,因为表达式类型列在语法中的表达式之后,但它显示在工具对话框中的表达式之前。这是因为表达式类型有一个默认值,即 Python 3。请注意,在工具对话框中,表达式类型被称为 Python 3,但在脚本中使用该函数时,正确的表达式类型写为 PYTHON3。因为它是默认值,所以通常不需要使用它。
考虑前面的示例,其中值从一个字段复制到另一个字段。以下脚本将新文本字段添加到要素类并使用计算字段工具将值从现有字段 CODE 复制到新字段,如下所示:

import arcpy
arcpy.env.workspace = "C:/Demo/City.gdb"
fc = "parcels"
arcpy.AddField_management(fc, "NEWCODE", "TEXT", "", "", "20")
arcpy.CalculateField_management(fc, "NEWCODE", "!CODE!"

也可以使用前面讨论的任何表达式。然而,使用代码块有点不同,因为代码块由多行组成。解决方案是使用跨多行的字符串变量,使用三引号,如下所示:

import arcpy
arcpy.env.workspace = "C:/Demo/City.gdb"
fc = "parcels"
arcpy.AddField_management(fc, "LU_NUM", "SHORT")
expression = "reclass(!LU_TXT!)"
codeblock = """
def reclass(landuse):
    if (landuse == "GOVERNMENT"):
        return 1
    elif (landuse == "INSTITUTIONAL"):
        return 2
    else:
        return 3"""
arcpy.CalculateField_management(fc, "LU_NUM", expression, "", 
                                codeblock)

尽管可以使用计算字段工具更新字段值,但另一种解决方案是使用更新游标。例如,在前面的示例中,根据 LU_TXT 字段中的值更新 LU_NUM 字段,您将更新光标设置在这两个字段上,然后使用类似的 if-else 结构来分配新值。
作为对比,使用更新游标的代码方案如下:

import arcpy
arcpy.env.workspace = "C:/Demo/City.gdb"
fc = "parcels"
arcpy.AddField_management(fc, "LU_NUM", "SHORT")
with arcpy.da.UpdateCursor(fc, ["LU_TXT", "LU_NUM"]) as cursor:
    for row in cursor:
        if row[0] == "GOVERNMENT":
            row[1] = 1
        elif row[0] == "INSTITUTIONAL":
            row[1] = 2
        else:
            row[1] = 3
        cursor.updateRow(row)

两种解决方案同样有效,尽管使用更新光标的解决方案更短,因为它不需要创建自定义函数。
顺便提一下 Arcade,因为 Arcade 表达式可以在 Python 脚本中使用。
考虑前面的例子,其中一个字段是对数转换的。可以使用计算字段工具中的以下 Python 表达式来完成此任务:

LOG_VALUE = math.log(!VALUE!)

Arcade 表达式也引用字段名称,但字段名称以 $feature 开头。 Arcade 有许多内置函数,包括 log()。完成相同计算的 Arcade 表达式如下:

LOG_VALUE = log($feature.VALUE)

除了语法差异之外,在计算字段工具中编写 Arcade 表达式时,只有一个代码块,而不是表达式和​​代码块的单独条目。在 Tool 对话框中,此代码如图所示。
在这里插入图片描述


import arcpy
arcpy.env.workspace = "C:/Demo/City.gdb"
fc = "parcels"
arcpy.AddField_management(fc, "LOG_VALUE", "DOUBLE")
                          expression = "log($feature.VALUE)"
arcpy.CalculateField_management(fc, "LOG_VALUE", expression, 
                                "ARCADE"

8.7 处理文本文件

到目前为止,您在本书中使用的大部分数据,例如路径、值、值列表等,都位于脚本本身或 GIS 格式的数据文件中,例如 shapefile、地理数据库和数据库表。然而,在许多情况下,数据也位于纯文本文件或其他表格数据格式中。 Python 有几个函数可以处理不同的格式。在许多情况下,这些文件来自其他应用程序,Python 可用于处理这些文件以在 ArcGIS Pro 中使用。本节检查纯文本文件 (.txt) 的使用。

open() 函数打开文本文件

open(name, {mode}, {buffering})

仅使用文件名作为参数会返回您可以读取的文件对象。如果您想做其他事情,例如写入文件,则必须通过指定模式明确说明。最常见的模式值如下: r:读模式,w:写模式,+:读/写模式(添加到另一种模式),b:二进制模式(添加到另一种模式,例如 rb、wb 等),a : append mode 如果没有提供 mode 参数,默认使用读取模式。写入模式允许您写入文件。可以将读/写模式添加到任何其他模式中,以指示允许读取和写入。二进制模式允许您更改文件的处理方式。默认情况下,Python 假定您正在处理包含字符的文本文件。如果您正在使用其他类型的文件(例如图像),则可以将 b 添加到模式中,例如“rb”。追加模式意味着写入文件的任何数据都会自动添加到文件末尾。
buffering 参数控制文件的缓冲。使用缓冲时,Python 可能会使用内存而不是磁盘空间来提高性能。对于适度的文件大小,通常不需要缓冲。
要创建一个新的文本文件,您可以使用 open() 函数并指定写入模式:

f = open("C:/Data/mytext.txt", "w")

存在几种文件方法来操作文本文件的内容,**包括 write()、read() 和 close()。**考虑以下示例:

f = open("C:/Data/mytext.txt", "w")
f.write("Geographic Information Systems")
f.close()

运行此代码会创建一个新的文件对象。如果文件 mytext.txt 已经存在,则现有文件将被覆盖,所以要小心。如果您在其他人使用的脚本中以这种方式创建文件,您可能需要添加检查以确定文件是否已存在。 write() 方法将字符串写入文件,close() 方法关闭文件(并保存其内容)。

读取文件:

f = open("C:/Data/mytext.txt")
f.read()

'Geographic Information Systems'

注意:本节中的代码示例假设您在交互式解释器中运行代码。
通过添加打印消息,您可以使用脚本获得相同的结果。
当打开一个文件只是为了读取它的内容时,没有必要指定一个模式,因为读取模式是默认的。 read() 方法用于读取文本文件的内容。如果未指定参数,脚本将读取文件的全部内容。可以提供一个可选参数来指示要读取的字符数。

大多数文本文件由多行组成,并且有几种文件方法可以处理行。您可以使用 r**eadline() 方法读取一行。**要读取文件的所有行并将它们作为列表返回,可以使用 readlines() 方法。
接下来,考虑一些例子。考虑文本文件,如图所示。
在这里插入图片描述
读取该文件的内容可以通过多种方式完成,从 read() 方法开始,如下所示:

f = open("C:/Data/sqltext.txt")
f.read()
'Structured\nQuery\nLanguage'

请注意,read() 方法读取所有行并将结果作为单个字符串返回。返回的文本文件中的行分隔符是字符 \n。
接下来是 readline() 方法。例如:

f = open("C:/Data/sqltext.txt")
f.readline()
'Structured\n'
f.readline()
'Query\n'
f.readline()
'Language'

readline() 方法从文本文件中读取下一行并将其作为字符串返回。继续使用 readline() 方法会返回后面的行。行分隔符 (\n) 也被返回。
最后,readlines() 方法读取文件中的所有行并将结果作为列表返回。例如:

f = open("C:/Data/sqltext.txt")
f.readlines()
['Structured\n', 'Query\n', 'Language']

可以使用 write() 和 writelines() 方法来编写多行文件。
要添加新行,必须使用行分隔符 (\n)。例如:

f = open("C:/Data/tintext.txt", "w")
f.write("Triangulated\nIrregular\nNode")
f.close()

运行此代码会创建一个包含三行的新文本文件,如图所示。
在这里插入图片描述
writelines() 方法可用于修改一行的字符串。例如:

f = open("C:/Data/tintext.txt")
lines = f.readlines()
f.close()
lines[2] = "Network"
f = open("C:/Data/tintext.txt", "w")
f.writelines(lines)
f.close()

在此示例中,readlines() 方法用于将文本文件的内容作为列表返回。然后关闭文件,并为列表中的一个元素分配一个新值。文件以写入模式再次打开,writelines() 方法用于更新该行的字符串值。运行此代码会生成图中所示的文本文件。
请记住,新行不会自动添加,这意味着您必须使用行分隔符 (\n) 自己添加它们。

通常,您应该通过调用 close() 方法来关闭文件。当您以读取模式打开文件时,调用此方法并不重要,因为当您退出使用该文件的程序时,文件对象会自动关闭。

处理文件时,从逻辑上讲,您要做的第一件事就是打开它们。如前面的示例所示,最常用的打开方法是使用内置的 open() 函数。

如何正确关闭文件

通常,当脚本终止时,打开的文件将自动关闭,但没有确切的方法来确切知道何时发生这种情况。这种不确定的状态会导致不良行为。关闭文件还可以防止文件被不必要地锁定。写入文件时,应始终在完成后将其关闭,因为 Python 可能会将您写入的数据缓存在内存中,如果程序崩溃,则可能根本不会写入数据。因此,最好在脚本中正确关闭文件。
关闭文件的另一种方法是使用 with 语句,它采用以下形式:

with open(<file>) as <variable>:
    <code to process file>

一旦 with 代码块完成, with 语句会自动关闭文件,即使在出现错误的情况下也是如此。在这种情况下,不需要使用 close() 方法。因此,强烈建议在打开文件时使用 with 语句。它会产生更清晰的代码并有助于处理错误。基于前面的示例,以下代码使用 with 语句创建一个新的空文本文件并写入一些文本:

with open("C:/Data/with.txt", "w") as f:
    f.write("Use more with statements.")

可以使用 close() 方法关闭文件,如前面的示例所示。通过使用 try-finally 结构,可以使这种方法更加健壮。例如:

f = open("mytext.txt")
try:
    <code to process file>
finally:
    f.close()

try-finally 结构的使用确保文件被关闭,而不管前面的代码行中是否有任何错误。
注意:使用 with 语句代表最佳实践,因此不建议使用close
在前面的示例中,您看到了如何将新值写入特定行。使用 Python 修改文本文件是一种常用的技术。来自其他应用程序的许多数据文件都是文本格式,但 ArcGIS Pro 不能直接使用。您可以使用 Python 自动执行此任务,而不是手动操作文本文件。在前面的示例中,在特定位置进行了更改。然而,更常见的是执行查找和替换搜索,该搜索将在必要时对文本进行更改。
考虑以下包含地理坐标的文本文件示例:

ID: 1, Latitude: 35.099722, Longitude: -106.527550
ID: 2, Latitude: 35.133015, Longitude: -106.583581
ID: 3, Latitude: 35.137142, Longitude: -106.650632
ID: 4, Latitude: 35.093650, Longitude: -106.573590

为了使文件更易于使用,您希望它如下所示:

1 35.099722 -106.527550
2 35.133015 -106.583581
3 35.137142 -106.650632
4 35.093650 -106.573590

一种方法是在文本编辑器中打开文件并执行查找和替换搜索。但是,同样可以直接在 Python 中完成。它要求您遍历文件的内容,并重复执行相同的操作。有几种迭代方法。在大多数情况下,您可以坚持使用一种方法,但了解一些不同的选项很有用,尤其是在尝试理解其他人的代码时。
尽管迭代单个字符可能很有用,但更常见的是迭代文本文件中的行。有几种方法可以遍历文本行。
首先,**Python 中的文件可以直接在 for 循环中使用来遍历它们的行。**代码如下:

with open("C:/Data/mytext.txt") as f:
    for line in f:
        <processing>

这段代码可能是对文本行进行迭代的最优雅的版本,因为代码很短并且直接利用了您可以迭代文件中的行的事实。
迭代也可以使用 readlines() 方法完成。例如:

with open("C:/Data/mytext.txt") as f:
    while True:
        line = f.readline()
        if not line:
            break
        <processing>

对于相对较小的文件,您可以使用 read() 方法(将整个文件读取为字符串)或 readlines() 方法(将文件读入字符串列表)一步读取整个文件。例如:

with open("C:/Data/mytext.txt") as f:
    for line in f.readlines():
        <processing>

使用 read() 方法或 readlines() 方法读取整个文件可能会占用过多的内存。
一种替代方法是使用带有 readline() 方法的 while 循环。第二种选择是使用 fileinput 模块而不是 open() 函数。该模块允许您创建一个可以在 for 循环中迭代的对象。以下示例使用了 fileinput 模块的 input() 函数,这类似于在使用 ArcPy 处理要素类和函数时使用游标:

import fileinput
with fileinput.input("C:/Data/mytext.txt") as f:
    for line in f:
        <processing>

您使用的方法在很大程度上是一个偏好问题,但是当文件可能很大时,通常会使用 fileinput。
现在您已经了解了逐行迭代的一般结构,是时候查看一个实际示例并重新访问我们一直在使用的文本文件,称为坐标.txt,如图所示。
在这里插入图片描述
假设您希望将其缩减为一个文本文件,其中仅包含由空格分隔的相关属性值,而没有字段名称(ID、纬度、经度)。您可以通过遍历行并使用字符串的 replace() 方法来完成此操作。处理文本文件时,最好将结果保存到新文件中。这样,如果代码没有完全按预期执行,您就不会丢失任何原始数据。
以下脚本以 read() 模式打开现有文件,并以 write() 模式创建新的输出文件。 for 循环用于遍历输入文件中的行。在下面的代码块中,replace() 方法被使用了 3 次以从每一行中删除特定的字符串。结果字符串被写入输出文件。代码如下:

with open("C:/Data/coordinates.txt") as input:
    with open("C:/Data/coordinates_clean.txt", "w") as output:
        for line in input:
            mystr = line.replace("ID: ", "")
            mystr = mystr.replace(", Latitude:", "")
            mystr = mystr.replace(", Longitude:", "")
            output.write(mystr)

该示例还说明了嵌套 with 语句的使用——第一个语句读取现有文本文件,第二个语句写入新的空文本文件。使用嵌套 with 语句的另一种方法是将它们放在一行代码中的组合语句中,如下所示:

with open("C:/Data/coordinates.txt") as input, open(
          "C:/Data/coordinates_clean.txt", "w") as output:

组合语句的使用减少了对额外缩进级别的需求,但代码行可能会变得冗长而复杂。
运行此代码会生成图中所示的文本文件。
在这里插入图片描述

8.8 CSV格式文件的使用

尽管文本文件被广泛使用,但它们通常缺乏标准化的格式。例如,如果必须将文本文件转换为数据库表,则通常必须打开每个文本文件以确定需要进行何种清理。作为替代方案,另一种广泛使用的格式是**逗号分隔值 (CSV)。**顾名思义,CSV 文件由没有任何格式的纯文本组成,但感兴趣的值用逗号分隔。
附图显示了一个示例 CSV 文件。
在这里插入图片描述
该文件看起来像一个纯文本文件,但感兴趣的值用逗号分隔。值之间没有空格。通过保存具有 .csv 文件扩展名的现有文本文件,或通过从电子表格或数据库应用程序导出文件来创建 CSV 文件。
如果您使用的是 Microsoft Office,则在 Windows 操作系统中查看 CSV 文件可能会产生误导,因为它们显示为 Microsoft Excel CSV 文件。这是 Microsoft Office 使用的文件类型关联,CSV 文件与常规 Excel 文件不同。但是,当您在 Windows 的文件资源管理器中双击 CSV 文件时,该文件会像 Excel 工作表一样打开。

通过使用内置的 csv 模块,可以在 Python 脚本中使用 CSV 文件。 csv 模块包含处理 CSV 文件所需的所有功能,最值得注意的是 csv.reader() 函数。
考虑以下示例来读取 CSV 文件的内容:

import csv
with open("C:/Data/csv_example.csv") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)
 
['ID', 'POINT_X', 'POINT_Y']
['1', '510812.53', '3899995.64']
['2', '510594.00', '3899400.97']
['3', '509414.30', '3898450.97']
...

您首先导入 csv 模块并在 with 语句中使用 open() 函数打开 CSV 文件。
接下来,csv.reader() 函数逐行或逐行读取文件的内容。这类似于设置游标,尽管 ArcPy 使用游标类,而 csv.reader() 是一个函数。
csv.reader() 函数可以遍历行,并且对于每一行(或行),该函数返回一个值列表。因为结果是一个列表,所以操作起来很方便。例如,您可以使用索引获取 ID 值:

print(row[0])

以类似的方式,您可以将坐标分配给变量。有一个小问题,即这个特定 CSV 文件的第一行。第一行包含一个包含字段名称的标题。尽管这是相关信息,但您不需要这些值来创建坐标对表。
您可以在迭代之前使用 Python 的内置 next() 函数跳过第一行。此函数确保迭代从坐标信息开始的第二行开始。
以下代码读取 CSV 文件,跳过第一行,并将 ID 号和坐标分配给变量:

import csv
with open("C:/Data/csv_example.csv") as f:
    reader = csv.reader(f)
    next(reader)
    for row in reader:
        ID = row[0]
        xcoord = row[1]
        ycoord = row[2]
        print(ID, xcoord, ycoord)

1 510812.53 3899995.64
2 510594.00 3899400.97
3 509414.30 3898450.97
4 510486.66 3898251.44
...

打印只是作为另一个任务的临时占位符,例如使用坐标创建新功能。第 9 章涵盖了这项任务。
尽管可以使用 Python 直接操作 CSV 文件的内容,但使用表作为输入参数的地理处理工具通常接受 CSV 文件作为有效输入。例如,XY 表到点工具根据表中的 x,y 坐标创建一个新的点要素类,该表可以是 CSV 格式。以下代码说明了 XY 表到点工具的示例:

import arcpy
arcpy.env.workspace = "C:/Data"
csvfile = "csv_example.csv"
outfc = "testpoints.shp"
arcpy.XYTableToPoint_management(csvfile, outfc, "POINT_X", "POINT_Y")

Points to remember

The ArcPy data access module, arcpy.da, provides support for editing and working with cursorsto manipulate data.

Cursors can iterate over rows in a table. Iteration is typically accomplished using a for loop or awith statement.

Search cursors iterate over records and find features of interest. Insert cursors add new recordsand create new features. Update cursors make changes, including modifying attribute values anddeleting records.

SQL expressions in Python can query data using search cursors. Queries carried out using SQL in Python use a WHERE clause. Proper syntax of queries is facilitated using the AddFieldDelimiters() function. Other supported SQL clauses include DISTINCT, GROUP BY, ORDER, and TOP.

Table and field names can be validated using the ValidateTableName() and ValidateFieldName() functions, respectively. These functions convert all invalid characters into an underscore (_). The CreateUniqueName() function can create a unique name by adding a number to an existing name.

Table and field names can be parsed into separate elements using the ArcPy parsing functions ParseTableName() and ParseFieldName(). Python is also used to write expressions in the Calculate Field tool. This includes basic expressions to calculate field values on the basis of another existing field, as well as more complex calculations using custom functions in a code block.

The contents of text files can be manipulated in Python. The open() function creates a file object, and several methods can be used to read and write text, including read(), readline(), readlines(), write(), and writelines(). One of the more common operations on files is to iterate over their lines to perform the same manipulation repeatedly, such as replacing strings to make the text files more usable.

CSV files represent a widely used alternative to text files when working with tabular data. Python’s built-in csv module can be used to read the contents of CSV files.

ArcPy 数据访问模块 arcpy.da 支持编辑和使用游标来操作数据。游标可以遍历表中的行。迭代通常使用 for 循环或 with 语句来完成。搜索游标遍历记录并找到感兴趣的特征。插入游标添加新记录并创建新功能。更新游标进行更改,包括修改属性值和删除记录。

Python 中的 SQL 表达式可以使用搜索游标查询数据。在 Python 中使用 SQL 执行的查询使用 WHERE 子句。使用 AddFieldDelimiters() 函数有助于查询的正确语法。其他受支持的 SQL 子句包括 DISTINCT、GROUP BY、ORDER 和 TOP。

可以分别使用 ValidateTableName() 和 ValidateFieldName() 函数来验证表名和字段名。这些函数将所有无效字符转换为下划线 (_)。 CreateUniqueName() 函数可以通过将数字添加到现有名称来创建唯一名称。
可以使用 ArcPy 解析函数 ParseTableName() 和 ParseFieldName() 将表和字段名称解析为单独的元素。
Python 还用于在计算字段工具中编写表达式。这包括基于另一个现有字段计算字段值的基本表达式,以及使用代码块中的自定义函数进行更复杂的计算。
文本文件的内容可以在 Python 中进行操作。 open() 函数创建一个文件对象,可以使用多种方法来读取和写入文本,包括 read()、readline()、readlines()、write() 和 writelines()。对文件更常见的操作之一是迭代它们的行以重复执行相同的操作,例如替换字符串以使文本文件更可用。
CSV 文件代表了在处理表格数据时广泛使用的文本文件替代方案。
Python 内置的 csv 模块可用于读取 CSV 文件的内容。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值