公司动态

ArcGIS Pro空间数据预处理实战:为机器学习准备地理信息数据

📅 2026/9/1 16:33:47
ArcGIS Pro空间数据预处理实战:为机器学习准备地理信息数据
在空间数据分析和机器学习项目中数据预处理是决定模型成败的关键环节。许多开发者尤其是刚接触地理信息系统的朋友常常在数据清洗、坐标转换和格式统一上耗费大量时间网上资料又过于零散。本文将聚焦于使用 ArcGIS Pro 进行空间数据预处理系统性地讲解从数据加载、投影转换、裁剪、属性清洗到最终导出为机器学习友好格式的全流程。无论你是 GIS 初学者还是希望将空间数据融入机器学习模型的开发者都能从这篇实战指南中找到可复用的代码和清晰的思路。1. 空间数据预处理的核心概念与重要性在将空间数据如矢量点、线、面或栅格影像输入机器学习模型之前我们必须对其进行一系列标准化操作这个过程就是空间数据预处理。其核心目标在于消除数据中的不一致性、错误和冗余确保数据质量从而让机器学习算法能够更高效、更准确地学习数据中的潜在规律。1.1 为什么空间数据预处理至关重要与传统的表格数据不同空间数据自带地理位置属性这使得其预处理过程更为复杂也更为关键。坐标系统一不同来源的数据可能使用不同的坐标系如 WGS84 地理坐标系、各种投影坐标系。如果直接将它们叠加分析或输入模型会导致位置错乱分析结果毫无意义。预处理的第一步往往是进行投影转换将所有数据统一到同一坐标系下。数据范围对齐我们可能只关心某个特定区域如某个城市、某个流域。通过裁剪Clip操作可以剔除研究区以外的数据减少数据量提升后续处理和分析的效率。属性字段标准化空间数据的属性表中可能包含空值、异常值、不一致的格式如日期格式混乱或对模型无意义的字段。清洗这些属性是特征工程的基础。几何错误修复矢量数据中可能存在拓扑错误如面状要素自相交、线状要素悬挂等。这些错误会影响空间分析如叠加分析、缓冲区分析的准确性进而影响基于这些分析结果构建的模型特征。格式转换机器学习库如 Scikit-learn, PyTorch通常无法直接读取.shp或.gdb文件。预处理需要将空间数据转换为如GeoJSON、CSV附带坐标或栅格数组如 NumPy Array等通用格式。1.2 机器学习中常见的空间数据预处理步骤一个完整的预处理流程通常遵循以下顺序我们将围绕 ArcGIS Pro 的功能展开数据加载与检查将不同来源的数据加载到 ArcGIS Pro 中并初步检查其坐标系、范围、属性表结构。投影与坐标转换将数据统一到适合分析区域和目标模型的坐标系。数据裁剪与掩膜提取根据研究区域边界裁剪出所需的空间范围。属性表清洗与字段计算处理空值、标准化字段、创建新特征如从坐标计算网格ID。几何修复与拓扑检查确保矢量数据的几何完整性。数据格式导出将处理好的数据导出为机器学习流程可读的格式。2. 环境准备与项目设置在开始实操前请确保你的环境已就绪。本文基于 ArcGIS Pro 3.x 版本进行演示其内置的 Python 环境通常为 ArcGIS Pro 自带的 Python 3.9和arcpy站点包是我们进行自动化处理的核心工具。2.1 软件与依赖ArcGIS Pro确保已安装 ArcGIS Pro 3.0 或更高版本。本文的操作和代码在该版本系列上测试通过。Python 环境使用 ArcGIS Pro 自带的 Python。你可以在 ArcGIS Pro 的“视图”选项卡中打开“Python”窗口或使用其内置的“笔记本”功能基于 Jupyter。必要的 Python 库arcpyArcGIS Pro 安装后自动可用是执行地理处理的基石。pandas,numpy用于高效的属性表操作和数值计算。可通过 ArcGIS Pro 的“包管理器”或命令行conda install pandas numpy安装。2.2 初始化 ArcGIS Pro 工程打开 ArcGIS Pro创建一个新的“地图”工程。在“目录”窗格中连接到你的工作文件夹。建议建立如下目录结构以保持项目整洁Your_Project_Folder/ ├── 01_原始数据/ │ ├── 研究区边界.shp │ ├── 兴趣点数据.shp │ └── 土地利用栅格.tif ├── 02_处理过程/ ├── 03_输出结果/ └── 04_脚本工具/将你的原始数据如.shp,.gdb,.tif文件拖放或导入到“01_原始数据”文件夹中。3. 核心预处理操作详解本章节将深入讲解每个核心预处理步骤在 ArcGIS Pro 中的实现方法包括图形界面操作和对应的arcpyPython 脚本以便你根据需求选择手动处理或编写自动化流程。3.1 投影转换 (Project)投影转换是将数据从一个坐标系转换到另一个坐标系的过程。对于机器学习确保所有输入图层在同一投影坐标系下是必须的。图形界面操作在“内容”窗格中右键点击需要转换的图层。选择“数据” - “导出要素”对于矢量或“数据” - “导出栅格”对于栅格。在导出对话框中点击“输出坐标系”旁的按钮选择目标坐标系例如针对中国区域分析常用的CGCS2000_3_Degree_GK_CM_120E。设置输出路径和名称点击“确定”。arcpy脚本实现# 导入arcpy模块 import arcpy import os # 设置工作空间 arcpy.env.workspace rC:\Your_Project_Folder\01_原始数据 arcpy.env.overwriteOutput True # 允许覆盖已有输出 # 定义输入要素和输出路径 input_feature 兴趣点数据.shp output_feature rC:\Your_Project_Folder\02_处理过程\兴趣点数据_投影后.shp # 定义目标坐标系 # 这里以 CGCS2000 3度带 120E 为例其WKID为 4547 target_coordinate_system arcpy.SpatialReference(4547) # 执行投影转换工具 try: arcpy.management.Project(input_feature, output_feature, target_coordinate_system) print(f投影转换成功: {output_feature}) except arcpy.ExecuteError as e: print(f投影转换失败: {e})关键参数解释arcpy.env.overwriteOutput设置为True可以避免因文件已存在而报错但在生产环境中需谨慎使用。arcpy.SpatialReference(4547)通过 WKID (Well-Known ID) 创建空间参考对象。你也可以使用投影文件路径 (arcpy.SpatialReference(r‘path\to\prjfile.prj‘)) 或名称字符串 (arcpy.SpatialReference(‘CGCS 2000 3 Degree GK Zone 40‘))。3.2 数据裁剪 (Clip)裁剪用于提取特定区域范围内的数据。研究区边界可以是一个面状要素如行政区划。图形界面操作在“分析”选项卡中点击“工具”打开“地理处理”窗格。搜索“裁剪”工具。“输入要素”选择待裁剪的图层如兴趣点。“裁剪要素”选择作为边界的图层如研究区边界。指定“输出要素类”的保存路径和名称。点击“运行”。arcpy脚本实现# 设置工作空间 arcpy.env.workspace rC:\Your_Project_Folder\02_处理过程 arcpy.env.overwriteOutput True # 定义输入、裁剪范围和输出 input_to_clip 兴趣点数据_投影后.shp clip_feature rC:\Your_Project_Folder\01_原始数据\研究区边界.shp output_clipped rC:\Your_Project_Folder\02_处理过程\兴趣点_已裁剪.shp # 执行裁剪工具 try: arcpy.analysis.Clip(input_to_clip, clip_feature, output_clipped) print(f裁剪成功: {output_clipped}) except arcpy.ExecuteError as e: print(f裁剪失败: {e})注意事项裁剪工具要求“裁剪要素”必须是面状要素。对于栅格数据的裁剪应使用“按掩膜提取”工具 (arcpy.sa.ExtractByMask)。3.3 属性表清洗与字段计算干净的属性表是构建有效特征的基础。常见操作包括处理空值、删除无用字段、创建新字段、标准化字段值。图形界面操作右键点击图层选择“属性表”。处理空值可以手动编辑或使用“字段计算器”将空值替换为特定值如0或平均值。删除字段在表视图下右键点击字段名选择“删除”。创建新字段点击“表”选项下的“添加字段”设置名称和类型如文本、整型、浮点型。字段计算右键点击新字段列名选择“计算字段”使用 Python 表达式进行计算例如将两个数值字段相加。arcpy脚本实现import arcpy input_fc rC:\Your_Project_Folder\02_处理过程\兴趣点_已裁剪.shp # 1. 添加一个新字段用于存储分类ID短整型 field_name GridID field_type SHORT try: arcpy.management.AddField(input_fc, field_name, field_type) print(f字段 {field_name} 添加成功。) except arcpy.ExecuteError as e: print(f添加字段失败: {e}) # 2. 使用字段计算器基于X,Y坐标计算简单的网格ID # 假设我们将研究区划分为1000米*1000米的网格 code_block def calc_grid_id(x, y, origin_x, origin_y, cell_size): import math col math.floor((x - origin_x) / cell_size) row math.floor((y - origin_y) / cell_size) # 生成一个简单的唯一ID这里只是一个示例逻辑 return row * 1000 col expression calc_grid_id(!SHAPE!.centroid.X, !SHAPE!.centroid.Y, 500000, 3000000, 1000) try: arcpy.management.CalculateField(input_fc, field_name, expression, PYTHON3, code_block) print(字段计算完成。) except arcpy.ExecuteError as e: print(f字段计算失败: {e}) # 3. 删除不需要的字段谨慎操作建议先备份 fields_to_keep [‘FID‘, ‘Shape‘, ‘OBJECTID‘, ‘Name‘, ‘Type‘, ‘GridID‘] # 指定要保留的字段 fields_all [f.name for f in arcpy.ListFields(input_fc)] fields_to_delete [f for f in fields_all if f not in fields_to_keep and not f.startswith(‘Shape_‘)] # 保留几何字段 if fields_to_delete: arcpy.management.DeleteField(input_fc, fields_to_delete) print(f已删除字段: {fields_to_delete})3.4 几何修复与拓扑检查对于面状要素几何错误可能导致面积计算错误或空间关系判断失误。图形界面操作在“分析”选项卡 - “工具”中搜索“修复几何”。选择输入要素指定输出路径运行即可自动修复常见的几何问题如自相交、空几何。更复杂的拓扑检查如面重叠、缝隙可以使用“拓扑”工具集创建拓扑规则并进行验证。arcpy脚本实现input_fc_with_errors “面状数据.shp” output_fc_fixed “面状数据_已修复.shp” try: # 使用修复几何工具 arcpy.management.RepairGeometry(input_fc_with_errors, output_fc_fixed, “DELETE_NULL”, “ESRI”) print(f“几何修复完成: {output_fc_fixed}”) except arcpy.ExecuteError as e: print(f“几何修复失败: {e}”)4. 完整实战案例为机器学习准备城市兴趣点(POI)数据假设我们有一个城市兴趣点数据 (POI.shp) 和一个行政区划边界数据 (District.shp)目标是提取某个行政区内所有餐饮类POI并为其添加网格空间特征最后导出为CSV文件供机器学习使用。4.1 项目目标与数据说明目标预测城市不同网格内的餐饮店铺数量。原始数据POI.shp包含全市兴趣点属性有Name名称、Type类型如‘餐饮‘、‘购物‘、Address等。District.shp包含各个行政区面属性有Dist_Name区名。预期输出一个CSV文件每行代表一个 500m x 500m 的网格包含网格ID、中心点坐标、网格内餐饮POI数量等特征。4.2 分步处理流程与代码步骤1环境设置与数据加载import arcpy import pandas as pd import os # 设置环境 proj_folder r“C:\ML_GIS_Project” arcpy.env.workspace os.path.join(proj_folder, “02_处理过程”) arcpy.env.overwriteOutput True # 路径定义 poi_path os.path.join(proj_folder, “01_原始数据”, “POI.shp”) district_path os.path.join(proj_folder, “01_原始数据”, “District.shp”) target_district “浦东新区” # 假设我们只分析‘浦东新区‘步骤2按行政区裁剪POI数据# 首先从行政区数据中提取目标区域 district_lyr “target_district_lyr” where_clause f“Dist_Name ‘{target_district}‘” arcpy.management.MakeFeatureLayer(district_path, district_lyr, where_clause) # 裁剪POI数据 output_poi_clipped “POI_浦东新区.shp” arcpy.analysis.Clip(poi_path, district_lyr, output_poi_clipped) print(f“已裁剪出 {target_district} 的POI数据。”)步骤3筛选餐饮类POI并创建网格# 筛选餐饮类POI (假设Type字段中‘餐饮‘表示餐饮类) poi_lyr “poi_restaurant_lyr” arcpy.management.MakeFeatureLayer(output_poi_clipped, poi_lyr, “Type ‘餐饮‘”) # 创建渔网 (Fishnet) - 用于生成规则网格 extent arcpy.Describe(poi_lyr).extent cell_width “500” cell_height “500” output_fishnet “Fishnet_500m.shp” # 创建面状的渔网 arcpy.management.CreateFishnet(out_feature_classoutput_fishnet, origin_coordf“{extent.XMin} {extent.YMin}”, y_axis_coordf“{extent.XMin} {extent.YMin 100}”, cell_widthcell_width, cell_heightcell_height, number_rowsNone, number_columnsNone, corner_coordf“{extent.XMax} {extent.YMax}”, labels“NO_LABELS”, geometry_type“POLYGON”) print(“500米网格创建完成。”)步骤4空间连接 - 统计每个网格内的餐饮POI数量# 将POI点与网格面进行空间连接统计每个网格内的点数 output_spatial_join “Grid_POI_Count.shp” arcpy.analysis.SpatialJoin(target_featuresoutput_fishnet, join_featurespoi_lyr, out_feature_classoutput_spatial_join, join_operation“JOIN_ONE_TO_ONE”, join_type“KEEP_ALL”, match_option“CONTAINS”) print(“空间连接完成已统计网格内POI数量。”) # 默认生成的计数字段是 ‘Join_Count‘我们将其重命名为更易懂的名字 arcpy.management.AlterField(output_spatial_join, ‘Join_Count‘, ‘Restaurant_Count‘, ‘Restaurant_Count‘)步骤5计算网格中心点坐标并导出属性表# 添加字段存储中心点坐标 arcpy.management.AddField(output_spatial_join, “Center_X”, “DOUBLE”) arcpy.management.AddField(output_spatial_join, “Center_Y”, “DOUBLE”) # 计算每个网格面的中心点坐标 with arcpy.da.UpdateCursor(output_spatial_join, [“SHAPE“, “Center_X”, “Center_Y”]) as cursor: for row in cursor: centroid row[0].centroid # 获取几何中心 row[1] centroid.X row[2] centroid.Y cursor.updateRow(row) print(“网格中心点坐标计算完成。”) # 将属性表导出为 CSV output_csv os.path.join(proj_folder, “03_输出结果”, “grid_restaurant_features.csv”) # 使用TableToTable工具只导出我们关心的字段 fields_to_export [“OID“, “Restaurant_Count”, “Center_X”, “Center_Y”] # OID 是对象ID arcpy.conversion.TableToTable(output_spatial_join, os.path.dirname(output_csv), os.path.basename(output_csv), field_mapping“;”.join([f“{f} ‘{f}‘” for f in fields_to_export])) print(f“属性表已导出为 CSV: {output_csv}”)步骤6使用Pandas进行最终清洗与保存# 用pandas读取CSV进行最后处理 df pd.read_csv(output_csv) # 检查和处理空值将NaN的餐厅数量设为0 df[‘Restaurant_Count‘].fillna(0, inplaceTrue) # 将计数转换为整数类型 df[‘Restaurant_Count‘] df[‘Restaurant_Count‘].astype(int) # 可以添加衍生特征例如密度这里面积固定为0.25平方公里 cell_area_km2 0.25 df[‘Restaurant_Density‘] df[‘Restaurant_Count‘] / cell_area_km2 # 保存最终用于机器学习的数据集 final_output_path os.path.join(proj_folder, “03_输出结果”, “ml_ready_grid_data.csv”) df.to_csv(final_output_path, indexFalse) print(f“机器学习就绪数据已保存至: {final_output_path}”) print(df.head()) # 预览前几行数据4.3 结果说明运行上述脚本后你将在03_输出结果文件夹中得到ml_ready_grid_data.csv文件。其内容大致如下OIDRestaurant_CountCenter_XCenter_YRestaurant_Density15135200.53421800.220.020135700.53421800.20.0312135200.53421300.248.0这个数据集已经是一个标准的表格数据每一行代表一个空间网格包含了目标变量Restaurant_Count和特征Center_X,Center_Y,Restaurant_Density。你可以直接使用pandas和scikit-learn等库加载此 CSV 文件进行后续的特征工程、模型训练和预测。5. 常见问题与排查思路在 ArcGIS Pro 中进行空间数据预处理时你可能会遇到一些典型问题。下表列出了常见错误、原因及解决方案。问题现象可能原因排查与解决思路执行arcpy工具时报错9999991. 输入数据路径错误或不存在。2. 输出路径权限不足或文件夹不存在。3. 数据格式不支持或已损坏。4. 坐标系定义错误。1. 使用os.path.exists()检查输入输出路径。2. 确保输出目录有写入权限或手动创建目录。3. 尝试在 ArcGIS Pro 界面中手动打开数据确认其有效性。4. 使用arcpy.Describe(data).spatialReference.name检查数据的坐标系。投影转换后要素位置“飞”到很远的地方源数据和目标坐标系的定义可能被混淆例如地理坐标系和投影坐标系误用。1. 确认源数据的真实坐标系。2. 使用“投影”工具而非“定义投影”工具。“定义投影”是赋予或纠正坐标系信息不进行坐标变换。3. 对于栅格使用“投影栅格”工具。裁剪后结果为空1. 裁剪要素与输入要素的空间范围无交集。2. 裁剪要素图层本身为空或定义查询Definition Query导致其不可见。1. 检查两个图层的坐标系是否一致并在地图上查看其空间位置关系。2. 清除裁剪要素图层的定义查询或确保其包含有效的图形。字段计算器Python表达式执行失败1. 字段名拼写错误或使用了保留字。2. Python 语法错误。3. 字段类型不匹配如尝试将字符串写入整型字段。1. 在表达式内字段名需要用!括起来如!FieldName!。2. 在独立的 Python IDE 中先测试复杂表达式逻辑。3. 使用arcpy.ListFields()确认字段的确切名称和类型。arcpy在独立 Python 环境中无法导入未使用 ArcGIS Pro 自带的 Python 环境或环境变量未正确设置。1. 最可靠的方式通过 ArcGIS Pro 的“Python”窗口或“笔记本”运行脚本。2. 若需在外部 IDE如 PyCharm中使用需将其 Python 解释器设置为 ArcGIS Pro 自带的python.exe通常位于C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3下。处理大型数据时内存不足或速度极慢1. 一次性处理数据量过大。2. 未设置合适的处理范围或切片大小。3. 磁盘IO成为瓶颈。1. 尝试分块处理先按空间范围或属性将大数据分割成小块分别处理后再合并。2. 对于栅格使用“金字塔”和“统计值”可以提升显示和分析性能。3. 确保工作路径在 SSD 上并关闭不必要的后台程序。6. 最佳实践与工程建议将空间数据预处理流程工程化、规范化能极大提升机器学习项目的可重复性和协作效率。版本控制与文档化使用 Git 等工具对处理脚本、配置文件进行版本控制。为每个关键的数据处理步骤编写清晰的注释并维护一个README.md文件说明数据来源、处理流程、坐标系定义、字段含义等元数据。对原始数据和各阶段中间数据做好备份。参数化与模块化脚本不要将文件路径、坐标系WKID等硬编码在脚本中。应将其提取为脚本顶部的配置变量或使用配置文件如config.ini、settings.py。将通用的功能封装成函数例如一个通用的reproject_and_clip()函数提高代码复用率。def process_spatial_data(input_fc, output_fc, target_sr_wkid, clip_boundaryNone): “”“通用的投影和裁剪函数”“” # ... 实现细节 ... pass错误处理与日志记录在arcpy脚本中广泛使用try...except块捕获arcpy.ExecuteError。使用 Python 的logging模块替代print语句将处理进度、警告和错误信息记录到文件便于后期排查。import logging logging.basicConfig(filename‘data_preprocess.log‘, levellogging.INFO, format‘%(asctime)s - %(levelname)s - %(message)s‘) try: arcpy.management.Project(...) logging.info(‘投影转换成功。‘) except arcpy.ExecuteError as e: logging.error(f‘投影转换失败: {e}‘)性能优化使用游标Cursor当需要对属性表进行逐行复杂计算时使用arcpy.da.UpdateCursor或arcpy.da.SearchCursor比字段计算器更灵活高效。禁用中间输出在循环或批量处理中可以设置arcpy.env.addOutputsToMap False来禁止将每个中间结果添加到地图以提升速度。并行处理对于可以分块独立处理的任务如多个城市的相同分析研究使用arcpy.mp或 Python 的multiprocessing模块进行并行计算。数据质量持续验证在关键步骤后添加数据质量检查点。例如检查输出要素的数量是否在合理范围、属性字段是否有异常空值、空间范围是否正确等。可以编写简单的验证函数在流程中自动调用。def validate_feature_class(fc_path): count arcpy.management.GetCount(fc_path)[0] if int(count) 0: raise ValueError(f“输出要素类 {fc_path} 为空”) # 检查是否有几何错误 # ... 更多检查 ... logging.info(f“{fc_path} 基础验证通过共 {count} 个要素。”)为机器学习优化输出特征命名导出到CSV的字段名应清晰、简洁避免特殊字符和空格最好使用下划线连接如restaurant_count。处理类别特征如果原始数据中有文本类型的类别如POI类型“餐饮”、“购物”需要在ArcGIS Pro预处理阶段或导出后用Pandas/Scikit-learn将其转换为数值标签或独热编码。空间滞后特征考虑在预处理阶段就通过空间连接或邻域分析创建一些空间滞后特征如相邻网格的POI数量均值这些特征对许多空间预测模型非常有效。掌握 ArcGIS Pro 进行空间数据预处理是打通地理信息科学与机器学习的关键桥梁。从坐标系对齐、范围裁剪到属性清洗和格式导出每一步都影响着后续模型的输入质量。本文提供的从概念到代码的完整路径希望能帮助你构建起标准化、自动化的空间数据处理流水线。记住好的数据是成功模型的一半而耐心和细致的预处理正是获得好数据的不二法门。接下来你可以尝试将处理好的网格数据导入到 Scikit-learn 中构建一个简单的回归模型来预测餐厅密度从而完成从 GIS 处理到 ML 建模的完整闭环。