ArcPy按属性分割?Split工具怎么调?
很多同学搜索“ArcPy按属性分割?Split工具怎么调?”,其实背后常见的是两个相近但不同的需求:一种是按某个字段把一个图层拆成多个要素类,另一种是用一个面图层去切割输入要素,并按面图层字段命名输出结果。本文按 ArcPy 实战方式说明 Split 工具和按属性分割工具该怎么选、参数怎么填、代码怎么写。
引言:先判断你要的是哪一种 ArcPy按属性分割
在 ArcGIS Pro 和 ArcPy 中,“按属性分割”容易被叫混。你可能想做的是:
- 按字段值直接拆分图层:例如按行政区字段,把一个道路图层拆成“海淀区道路”“朝阳区道路”等多个要素类。
- 按另一个面图层切割:例如用区县边界面去切割道路,并按区县名称输出多个道路结果。
如果只是按输入图层自身字段拆分,优先用 Split By Attributes,ArcPy 中通常是 arcpy.analysis.SplitByAttributes。如果要用另一个面图层作为切割范围,则用 Split 工具,ArcPy 中是 arcpy.analysis.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 的字段,用于命名输出 | NAME、XZQDM、GRID_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_field 是 split_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。
实际项目中,建议优先输出到文件地理数据库,提前检查字段值、坐标系、几何有效性和输出数量。如果你需要更强的命名控制和异常处理,可以使用循环选择加导出的方式,它虽然代码更长,但更适合可重复运行的生产脚本。