ArcPy按属性分割?Split工具怎么调?

GIS基础理论
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

很多同学搜索“ArcPy按属性分割?Split工具怎么调?”,其实背后常见的是两个相近但不同的需求:一种是按某个字段把一个图层拆成多个要素类,另一种是用一个面图层去切割输入要素,并按面图层字段命名输出结果。本文按 ArcPy 实战方式说明 Split 工具和按属性分割工具该怎么选、参数怎么填、代码怎么写。

引言:先判断你要的是哪一种 ArcPy按属性分割

在 ArcGIS Pro 和 ArcPy 中,“按属性分割”容易被叫混。你可能想做的是:

  • 按字段值直接拆分图层:例如按行政区字段,把一个道路图层拆成“海淀区道路”“朝阳区道路”等多个要素类。
  • 按另一个面图层切割:例如用区县边界面去切割道路,并按区县名称输出多个道路结果。

如果只是按输入图层自身字段拆分,优先用 Split By Attributes,ArcPy 中通常是 arcpy.analysis.SplitByAttributes。如果要用另一个面图层作为切割范围,则用 Split 工具,ArcPy 中是 arcpy.analysis.Split

ArcPy按属性分割 Split工具按字段分割流程图
ArcPy 按属性分割时,先区分 Split By Attributes 和 Split 工具,避免参数填错。

背景:为什么 Split 工具经常调不通

很多 ArcPy 脚本报错,不是代码语法问题,而是工具理解错了。Split 工具不是简单地“按输入图层某个字段分组导出”,它需要一个 split_features,也就是用于切割的要素图层,通常是面要素。

Split 工具的典型逻辑是:

  • 输入要素:要被切割的数据,例如道路、地块、管线。
  • 分割要素:用于切割输入数据的面要素,例如区县边界、网格面。
  • 分割字段:分割要素中的字段,用来生成输出要素类名称。
  • 输出工作空间:保存多个输出结果的文件夹或地理数据库。

因此,如果你的数据只有一个图层,并且只是想按字段值拆成多个图层,直接调用 Split 往往会卡在 split_features 参数上。这时应该改用 Split By Attributes。

原理:Split 与 Split By Attributes 的核心区别

理解原理后,ArcPy按属性分割就不容易写错。

需求 推荐工具 ArcPy 函数 是否需要另一个分割图层
按输入图层自身字段值拆成多个输出 Split By Attributes arcpy.analysis.SplitByAttributes 不需要
用面图层切割输入要素,并按面图层字段输出 Split arcpy.analysis.Split 需要
只想导出某一个字段值对应的数据 Select / Export Features arcpy.management.SelectLayerByAttribute 不需要

Split By Attributes 本质上是分组导出。字段中有多少个有效类别,就可能生成多少个输出要素类。

Split 本质上是空间叠加切割。它先看输入要素落在哪些分割面内,再按分割面字段生成输出结果。它不仅看属性,还涉及空间位置和几何切割。

步骤:用 ArcPy 按字段值直接分割图层

如果你的目标是“按属性字段拆分一个图层”,例如按 XZQMC 字段拆分地块,推荐使用下面这种写法。

1. 准备输入数据和输出地理数据库

建议把输出结果放到文件地理数据库中,而不是普通文件夹。这样可以减少 Shapefile 字段名截断、中文编码、文件数量过多等问题。

import arcpy
import os

arcpy.env.overwriteOutput = True

in_features = r"D:gis_projectdata.gdbparcel"
out_workspace = r"D:gis_projectsplit_result.gdb"
split_fields = ["XZQMC"]

if not arcpy.Exists(out_workspace):
    arcpy.management.CreateFileGDB(
        out_folder_path=os.path.dirname(out_workspace),
        out_name=os.path.basename(out_workspace)
    )

arcpy.analysis.SplitByAttributes(
    Input_Table=in_features,
    Target_Workspace=out_workspace,
    Split_Fields=split_fields
)

print("按属性分割完成")

这段代码会根据 XZQMC 字段的不同值,在 split_result.gdb 中生成多个要素类。输出名称通常来自字段值,因此字段值最好不要包含特殊符号。

2. 处理中文、空值和非法名称

按属性分割最容易出问题的是字段值不能直接作为要素类名称。比如字段值包含空格、斜杠、括号、点号,或者以数字开头,都可能导致输出失败或名称被自动改写。

稳妥做法是先检查字段值:

import arcpy

in_features = r"D:gis_projectdata.gdbparcel"
field_name = "XZQMC"

values = set()
with arcpy.da.SearchCursor(in_features, [field_name]) as cursor:
    for row in cursor:
        values.add(row[0])

for value in sorted(values, key=lambda x: str(x)):
    print(value)

如果字段值很乱,建议先新建一个规范化字段,例如 SPLIT_NAME,把输出名整理成英文、拼音或短代码,再用该字段分割。

3. 多字段组合分割

如果你要按“区县 + 用地类型”组合分割,可以把多个字段传给 Split_Fields

import arcpy

arcpy.env.overwriteOutput = True

in_features = r"D:gis_projectdata.gdblanduse"
out_workspace = r"D:gis_projectlanduse_split.gdb"

arcpy.analysis.SplitByAttributes(
    Input_Table=in_features,
    Target_Workspace=out_workspace,
    Split_Fields=["DISTRICT", "LAND_TYPE"]
)

print("多字段按属性分割完成")

多字段分割会产生更多输出结果。运行前要确认字段组合数量是否过多,否则可能一次生成几百甚至几千个要素类,后续管理会很麻烦。

步骤:ArcPy Split 工具怎么调

如果你确实要调用 Split 工具,需要准备两个图层:一个是被切割的输入要素,另一个是用于切割的面要素。

1. Split 工具参数说明

参数 含义 常见填写示例
in_features 被切割的输入要素 道路、河流、地块、管线
split_features 用于切割的要素,通常是面图层 行政区、网格、规划分区
split_field 来自 split_features 的字段,用于命名输出 NAMEXZQDMGRID_ID
out_workspace 输出工作空间 文件地理数据库路径
cluster_tolerance 聚类容差,一般不建议随意填写 通常留空

2. 用行政区面切割道路的 ArcPy 示例

import arcpy
import os

arcpy.env.overwriteOutput = True

in_features = r"D:gis_projectdata.gdbroad"
split_features = r"D:gis_projectdata.gdbdistrict_boundary"
split_field = "XZQMC"
out_workspace = r"D:gis_projectroad_by_district.gdb"

if not arcpy.Exists(out_workspace):
    arcpy.management.CreateFileGDB(
        out_folder_path=os.path.dirname(out_workspace),
        out_name=os.path.basename(out_workspace)
    )

arcpy.analysis.Split(
    in_features=in_features,
    split_features=split_features,
    split_field=split_field,
    out_workspace=out_workspace
)

print("Split 工具分割完成")

这段脚本会用 district_boundary 面图层切割 road,并按 XZQMC 字段输出多个道路要素类。注意,split_field 必须来自 split_features,不是来自 in_features

3. 运行前检查坐标系

Split 是空间切割工具,输入要素和分割要素最好使用相同的投影坐标系。如果一个是 CGCS2000 地理坐标系,另一个是投影坐标系,虽然软件可能进行动态投影显示,但地理处理时仍建议先统一坐标系。

import arcpy

datasets = [
    r"D:gis_projectdata.gdbroad",
    r"D:gis_projectdata.gdbdistrict_boundary"
]

for ds in datasets:
    desc = arcpy.Describe(ds)
    print(ds)
    print(desc.spatialReference.name)

如果坐标系不一致,可以先使用 Project 工具把数据投影到同一个坐标系,再执行 Split。

常见坑:ArcPy按属性分割失败多半是这些原因

1. 把 Split 当成 Split By Attributes 用

这是最常见的问题。Split 需要 split_features,而 Split By Attributes 不需要。如果你只有一个输入图层,只想按字段拆分,请使用 arcpy.analysis.SplitByAttributes

2. split_field 填错图层

Split 工具中的 split_field 必须是分割要素 split_features 里的字段。如果你把输入道路图层里的字段填进去,工具会找不到字段或输出结果不符合预期。

3. 输出路径使用普通文件夹导致名称问题

普通文件夹输出 Shapefile 时,字段名、编码、文件名长度都会受限制。对于 ArcPy按属性分割,推荐输出到 .gdb 文件地理数据库。

4. 字段值包含非法字符

输出要素类名称不能随便包含 /:*?、空值等内容。字段值越规范,分割越稳定。

5. 面图层有重叠或缝隙

使用 Split 工具时,如果分割面之间有重叠,同一条线或同一个面可能被切到多个输出里;如果面之间有缝隙,落在缝隙中的输入要素可能不会进入任何输出结果。行政区、网格、规划分区应先做拓扑检查。

6. 数据量太大,一次输出太多结果

如果字段唯一值很多,Split By Attributes 会生成大量要素类。建议先统计字段唯一值数量,必要时分批处理。

import arcpy
from collections import Counter

in_features = r"D:gis_projectdata.gdbparcel"
field_name = "XZQMC"

counter = Counter()
with arcpy.da.SearchCursor(in_features, [field_name]) as cursor:
    for row in cursor:
        counter[row[0]] += 1

print("类别数量:", len(counter))
for key, count in counter.most_common(20):
    print(key, count)

方法比较:Split、Split By Attributes 和循环 Select 怎么选

方法 适合场景 优点 限制
SplitByAttributes 按输入图层字段值拆分 代码简洁,适合标准按属性分割 输出名称依赖字段值,字段值太乱时容易出问题
Split 用面图层切割输入要素 同时完成空间切割和按分割字段输出 必须有分割面,且要注意拓扑和坐标系
循环选择并导出 需要自定义输出名、过滤条件、日志和异常处理 最灵活,适合生产脚本 代码稍长,需要自己处理 SQL 和命名

如果你需要完全控制输出名称,可以不用 Split By Attributes,而是用字段唯一值循环选择并导出。

import arcpy
import os
import re

arcpy.env.overwriteOutput = True

in_features = r"D:gis_projectdata.gdbparcel"
out_workspace = r"D:gis_projectparcel_by_district.gdb"
field_name = "XZQMC"

def safe_name(value):
    text = str(value).strip()
    text = re.sub(r"[^0-9A-Za-z_u4e00-u9fa5]", "_", text)
    if not text:
        text = "EMPTY"
    return text[:50]

if not arcpy.Exists(out_workspace):
    arcpy.management.CreateFileGDB(
        out_folder_path=os.path.dirname(out_workspace),
        out_name=os.path.basename(out_workspace)
    )

values = sorted({
    row[0] for row in arcpy.da.SearchCursor(in_features, [field_name])
    if row[0] is not None
})

field_delimited = arcpy.AddFieldDelimiters(in_features, field_name)

for value in values:
    where_clause = "{} = '{}'".format(field_delimited, str(value).replace("'", "''"))
    out_name = safe_name(value)
    out_fc = os.path.join(out_workspace, out_name)

    arcpy.conversion.ExportFeatures(
        in_features=in_features,
        out_features=out_fc,
        where_clause=where_clause
    )

    print("已导出:", value, out_fc)

print("循环选择导出完成")

这种方法适合生产环境,因为可以加入日志、字段值清洗、异常跳过、空值处理和输出数量控制。

检查清单:运行 ArcPy Split 前逐项确认

  • 你是按字段拆分,还是用面图层切割?前者用 Split By Attributes,后者用 Split。
  • in_features 是否存在,并且要素数量不为 0?
  • 如果用 Split,split_features 是否为有效面图层?
  • split_field 是否来自 split_features
  • 输出工作空间是否建议使用 .gdb
  • 分割字段是否存在空值、重复异常值、特殊符号?
  • 输入数据和分割数据坐标系是否一致?
  • 分割面是否存在重叠、缝隙或无效几何?
  • 预计输出要素类数量是否可控?
  • 脚本中是否设置了 arcpy.env.overwriteOutput = True

FAQ:ArcPy按属性分割常见问题

1. ArcPy按属性分割到底用 Split 还是 SplitByAttributes?

如果只是按输入图层自己的字段值拆分,用 SplitByAttributes。如果要用另一个面图层切割输入要素,并按面图层字段输出,用 Split

2. Split 工具的 split_field 是哪个图层的字段?

split_fieldsplit_features 的字段,不是 in_features 的字段。这一点最容易填错。

3. Split By Attributes 输出名称乱码或不规范怎么办?

优先输出到文件地理数据库。如果字段值包含中文、特殊字符或很长的名称,建议先新建一个规范字段,例如 SPLIT_NAME,再按该字段分割。

4. ArcPy Split 可以按点或线图层分割吗?

Split 工具通常使用面要素作为分割要素更符合实际场景。若你的分割条件是点、线或普通属性筛选,通常应改用选择、叠加分析或字段分组导出,而不是强行使用 Split。

5. 为什么分割后有些要素没有输出?

常见原因是输入要素不在任何分割面范围内、分割面有缝隙、坐标系不一致、几何无效,或者字段值为空导致输出名称异常。建议先叠加显示检查空间关系,再运行修复几何和拓扑检查。

6. 数据很多时,SplitByAttributes 很慢怎么办?

可以先减少字段唯一值数量,清理无用字段,使用文件地理数据库,避免网络路径输出。对于超大数据,可以按区域或类别分批处理,并在脚本中记录每一批的运行日志。

结论:按属性分割先选对工具,再写 ArcPy

ArcPy按属性分割的关键不是先写代码,而是先判断任务类型。按输入图层自身字段拆分,用 arcpy.analysis.SplitByAttributes;用行政区、网格等面图层切割输入要素,则用 arcpy.analysis.Split

实际项目中,建议优先输出到文件地理数据库,提前检查字段值、坐标系、几何有效性和输出数量。如果你需要更强的命名控制和异常处理,可以使用循环选择加导出的方式,它虽然代码更长,但更适合可重复运行的生产脚本。