共计 2738 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点
在 GIS 与机器学习结合的项目中,我们经常需要将 ArcMap 中的标注数据导出为机器学习可用的训练集格式(如 CSV 或 TFRecord)。然而,直接使用 ArcMap 的导出功能往往会遇到以下问题:

- 属性丢失:从.shp 文件导出为 CSV 时,某些字段类型(如日期、二进制)可能无法正确保留
- 空间信息缺失:几何对象的空间属性(如坐标、面积)在转换过程中容易被简化为普通文本
- 坐标系不一致:不同数据源的坐标系差异会导致训练样本无法对齐
- 编码问题:标注文本中的特殊字符(如中文)可能出现乱码
机器学习训练集对空间数据有特殊要求:
- 坐标系需要统一(通常使用 WGS84 或项目指定坐标系)
- 几何特征需要转换为固定维度的数值表示(如 WKT 文本或坐标数组)
- 属性字段需要类型一致且无空值
技术方案
我们采用 arcpy+pandas 的组合方案解决上述问题:
- arcpy:用于读取 GIS 数据、提取几何特征、执行坐标系转换
- pandas:用于数据结构转换、空值处理和最终输出
关键处理流程:
- 读取要素类并动态获取字段信息
- 将几何对象转换为 WKT(Well-Known Text)格式
- 处理坐标系定义不一致问题
- 转换属性字段类型并处理空值
- 分块导出避免内存溢出
代码实现
以下是完整 Python 脚本(适用于 ArcGIS Pro 3.0+):
import arcpy
import pandas as pd
from charset_normalizer import detect
# 配置输入输出路径
input_fc = arcpy.GetParameterAsText(0) # 输入要素类
output_csv = arcpy.GetParameterAsText(1) # 输出 CSV 路径
# 动态获取字段列表(排除几何字段)fields = [f.name for f in arcpy.ListFields(input_fc)
if f.type not in ['Geometry', 'OID']]
geom_type = arcpy.Describe(input_fc).shapeType
# 定义几何转换函数
def geometry_to_wkt(geom):
if geom is None:
return None
if geom_type == 'Point':
return f"POINT ({geom.X} {geom.Y})"
elif geom_type == 'Polyline':
return 'LINESTRING (' + ','.join(f"{p.X} {p.Y}"
for part in geom
for p in part) + ')'
elif geom_type == 'Polygon':
return 'POLYGON (' + ','.join(','.join(f"{p.X} {p.Y}" for p in part)
for part in geom) + ')'
# 检测文本编码
def detect_encoding(text):
if not text:
return 'utf-8'
return detect(text.encode('raw_unicode_escape'))['encoding']
# 使用 SearchCursor 分块读取
chunk_size = 10000
data_chunks = []
with arcpy.da.SearchCursor(input_fc, ['SHAPE@'] + fields) as cursor:
chunk = []
for i, row in enumerate(cursor):
# 转换几何对象
wkt = geometry_to_wkt(row[0])
# 处理属性值
record = {'geometry': wkt}
for j, field in enumerate(fields, 1):
value = row[j]
if isinstance(value, str):
try:
value = value.encode(detect_encoding(value)).decode('utf-8')
except:
value = ''
record[field] = value
chunk.append(record)
# 分块处理
if len(chunk) >= chunk_size:
data_chunks.append(pd.DataFrame(chunk))
chunk = []
if chunk:
data_chunks.append(pd.DataFrame(chunk))
# 合并并保存结果
if data_chunks:
pd.concat(data_chunks).to_csv(output_csv, index=False, encoding='utf-8-sig')
else:
pd.DataFrame(columns=['geometry']+fields).to_csv(output_csv, index=False)
避坑指南
1. 文本编码问题
ArcGIS 默认使用系统本地编码(Windows 中文版通常是 GBK),而机器学习框架通常要求 UTF-8。解决方案:
- 使用
charset-normalizer库自动检测编码 - 输出时指定
encoding='utf-8-sig'解决 Excel 打开乱码问题
2. 大数据量处理
当要素超过 10 万条时:
- 使用
chunk_size参数控制内存使用 - 考虑先导出到多个 CSV 再合并
- 对于极大数据集,建议直接导出为 TFRecord 格式
3. 坐标系问题
确保输出数据的坐标系一致:
# 在脚本开头添加坐标系检查
input_sr = arcpy.Describe(input_fc).spatialReference
target_sr = arcpy.SpatialReference(4326) # WGS84
if input_sr.factoryCode != target_sr.factoryCode:
arcpy.AddWarning(f"坐标系不一致: {input_sr.name} -> {target_sr.name}")
# 可选:添加投影转换代码
动手实验
我们准备了一个包含典型问题的样例 GDB 文件:sample_data.gdb,其中包含:
- 混合坐标系的多边形数据
- 包含中文和特殊符号的标注字段
- 故意设置的异常空值
挑战任务:
- 修改上述脚本使其能正确处理该数据
- 将输出坐标系统一为 WGS84(EPSG:4326)
- 处理异常空值(建议填充为 ’NULL’ 字符串)
提示:可以使用 arcpy.Project_management() 进行坐标系转换,注意处理转换失败的情况。
总结
通过这套方案,我们实现了:
- 保留完整的空间属性信息
- 自动处理编码和类型转换
- 支持大数据量分块导出
- 保证输出数据符合机器学习要求
实际项目中,建议进一步封装为 ArcGIS 工具箱工具,添加进度条显示和错误重试机制。对于更复杂的场景,可以考虑结合 GeoPandas 进行高级空间运算。
正文完
