在实际的地理信息系统(GIS)和空间数据分析项目中,原始的空间数据(如矢量、栅格)很少能直接用于机器学习模型训练。数据中可能包含坐标系统不一致、属性字段缺失、空间分布不均、尺度差异巨大等问题,这些问题会直接导致模型训练失败或结果不可靠。空间数据预处理,正是为了解决这些问题,将原始地理数据转化为适合机器学习算法“消化”的标准化、规范化格式。
本文将以 ArcGIS Pro 作为核心工具,系统性地讲解面向机器学习的空间数据预处理全流程。无论你是 GIS 分析师、数据科学家,还是希望将空间分析能力融入机器学习项目的开发者,本文都将提供一个从概念到实践的可操作指南。我们将从理解空间数据的特殊性开始,逐步完成数据加载、坐标系统一、数据清洗、特征工程、样本划分等一系列关键步骤,最终生成可直接用于 Scikit-learn、PyTorch 等主流机器学习框架的数据集。整个过程将结合 ArcGIS Pro 的可视化界面和 ArcPy 脚本,确保操作可复现,逻辑可理解。
1. 理解空间数据预处理的特殊性
与传统的表格数据预处理相比,空间数据预处理的核心在于处理其固有的“空间”属性。这不仅仅是多了一列经度和纬度那么简单,它涉及到空间关系、坐标参考系统、拓扑规则等一系列独特的概念。忽略这些特殊性,直接套用传统数据处理流程,是许多空间机器学习项目失败的首要原因。
1.1 空间数据的核心要素
空间数据通常由两部分构成:几何信息和属性信息。几何信息定义了要素(如点、线、面)在地球表面的位置和形状;属性信息则以表格形式记录了每个要素的非空间特征(如人口、温度、类别)。
对于机器学习而言,我们需要从这两部分信息中提取有效的特征:
- 几何衍生特征:从几何信息中计算得出,如多边形的面积、周长、中心点坐标;线的长度、方向;点与点之间的距离、密度等。这些特征是空间数据独有的。
- 空间关系特征:描述要素之间的空间交互,如一个点是否落在某个多边形内(空间连接),一个要素的邻居有哪些(空间自相关),到最近道路的距离等。
- 属性特征:即属性表中的原始字段,需要进行传统的标准化、归一化、编码等处理。
1.2 坐标系:一切空间分析的基石
坐标系不一致是空间数据融合时最常见的“坑”。一个使用 WGS 1984 地理坐标系(单位:度)的数据,与另一个使用 UTM 投影坐标系(单位:米)的数据,无法进行直接的距离计算或叠加分析。
- 地理坐标系 (GCS):基于球面,用经纬度表示位置。适用于全球尺度,但距离和面积计算不精确。
- 投影坐标系 (PCS):将球面投影到平面,用米、英尺等单位表示位置。适用于区域分析,能进行精确的几何计算。
预处理关键步骤:在开始任何分析前,必须将所有数据投影到同一个、适合研究区域的投影坐标系下。在 ArcGIS Pro 中,可以使用“投影”工具。
1.3 空间数据预处理的通用流程
一个完整的面向机器学习的空间数据预处理流程,可以概括为以下几个阶段,后续章节将详细展开:
- 数据获取与加载:收集并导入各类空间数据。
- 坐标系统一与数据对齐:确保所有数据在同一空间参考下。
- 数据清洗与质量检查:处理几何错误、属性空值、异常值。
- 特征工程:从几何和属性中构造、选择和转换特征。
- 样本创建与划分:生成训练、验证、测试集,并注意空间自相关带来的“数据泄漏”风险。
- 数据导出:将处理好的数据转换为机器学习框架可读的格式(如 CSV、NumPy 数组、GeoPackage)。
2. 环境准备与核心工具
在开始实操前,需要准备好软硬件环境,并熟悉我们将要使用的主要工具。
2.1 软件与许可
- ArcGIS Pro:版本建议为 3.0 或更高。需要拥有有效的 ArcGIS 许可(如通过组织账号或个人试用版)。确保安装时勾选了“Python”组件,这将自动安装 ArcGIS Pro 内置的 Python 环境(通常包含
arcpy库和基础的数据科学包)。 - Python 环境(可选但推荐):虽然 ArcGIS Pro 内置了 Python,但对于更复杂的机器学习流水线,你可能希望使用独立的 Conda 环境。可以通过 ArcGIS Pro 自带的“Python 命令提示符”来管理环境。
2.2 ArcGIS Pro 中的关键工具窗格
- 目录窗格:用于浏览和管理地理数据库、文件夹连接中的数据集。
- 内容窗格:管理当前地图中的图层,控制图层的显示顺序、符号化等。
- 地理处理窗格:这是执行所有分析工具的入口。可以通过搜索框快速找到工具,如“投影”、“融合”、“要素转点”等。
- Python 窗格:可以直接编写和运行 Python 代码,调用
arcpy库。这对于自动化重复性预处理任务至关重要。
2.3 初始项目设置
- 打开 ArcGIS Pro,创建一个新的“地图”项目。
- 在“目录”窗格中,右键点击“文件夹”,添加一个连接到你的工作文件夹的链接。所有数据和处理结果都将存放在此。
- 将你的原始数据(如 Shapefile、File Geodatabase、TIFF 影像等)拖拽或导入到地图视图中。
3. 坐标系统一与数据基础处理
这是预处理的第一步,也是确保后续所有空间计算正确的关键。
3.1 检查并统一坐标系
- 检查坐标系:在“内容窗格”中,右键点击某个图层,选择“属性”,切换到“源”选项卡。这里可以看到该图层的当前坐标系信息。
- 确定目标坐标系:选择的标准是:对于需要进行距离、面积计算或机器学习建模的区域性研究,必须使用投影坐标系。例如,研究中国区域,常用
WGS 1984 UTM Zone 50N。 - 执行投影:
- 方法一(界面操作):在“地理处理”窗格中搜索“投影”工具。设置输入数据集、输出位置,并在“输出坐标系”参数中选择或输入你确定的目标坐标系。
- 方法二(Python脚本):在 Python 窗格中运行以下代码,实现批量投影。
import arcpy import os # 设置工作空间和输出坐标系 arcpy.env.workspace = r"C:\YourData\RawData.gdb" # 输入地理数据库或文件夹 output_coordinate_system = arcpy.SpatialReference(32650) # 例如:WGS84 UTM 50N, EPSG:32650 # 列出所有要素类 feature_classes = arcpy.ListFeatureClasses() for fc in feature_classes: output_name = f"{fc}_Projected" output_path = os.path.join(r"C:\YourData\Processed.gdb", output_name) # 执行投影 arcpy.management.Project(fc, output_path, output_coordinate_system) print(f"已投影: {fc} -> {output_name}")注意:
Project工具会创建新的数据集,原始数据保持不变。对于栅格数据,使用“投影栅格”工具。
3.2 处理空值字段
搜索词中提到了“将部分字段值<空>变成0”,这是一个典型的数据清洗需求。空值(NULL)在机器学习中可能导致计算错误,通常需要填充或删除。
- 识别空值:在图层属性表中,空值单元格显示为
<空>。 - 使用字段计算器填充:
- 右键点击需要填充的字段列标题,选择“计算字段”。
- 在“字段计算器”对话框中,编写 Python 表达式。例如,将名为
Population字段的空值填充为 0:# 表达式 def fill_null(value): return value if value is not None else 0 - 在“表达式”框中输入:
fill_null(!Population!)。
- 使用
arcpy批量处理:import arcpy fc = r"C:\YourData\Processed.gdb\Cities_Projected" field = "Population" # 使用更新游标 with arcpy.da.UpdateCursor(fc, [field]) as cursor: for row in cursor: if row[0] is None: # 判断是否为空 row[0] = 0 # 填充为0 cursor.updateRow(row) print("空值填充完成。")
决策点:填充为0并非唯一选择。对于数值字段,也可以填充为均值、中位数;对于类别字段,可以填充为“未知”类别。选择取决于业务逻辑。
4. 特征工程:从空间数据中构造有效特征
特征工程是机器学习的灵魂,对于空间数据尤其如此。我们需要将空间信息转化为数值型特征。
4.1 几何特征提取
直接从要素的几何形状中计算特征。
| 要素类型 | 可提取特征 | 对应工具(ArcGIS Pro) | 说明 |
|---|---|---|---|
| 面 (Polygon) | 面积、周长、中心点(X,Y)、最小外接矩形参数 | 计算几何属性工具 | 面积和周长是基础但重要的特征。中心点坐标可用于后续的空间关系计算。 |
| 线 (Polyline) | 长度、起点/终点坐标、方向 | 计算几何属性工具 | 长度是核心特征。方向(如道路走向)在某些模型中可能有用。 |
| 点 (Point) | 坐标(X, Y, Z) | 属性表中已存在 | 最直接的特征。对于三维点,Z值可能是重要特征。 |
操作示例(为面要素添加面积字段):
- 在内容窗格中右键点击面图层,选择“属性表”。
- 点击表左上角的“添加”按钮,新建一个双精度字段,命名为
Area_sqkm。 - 右键点击新字段列标题,选择“计算字段”。
- 在“字段计算器”中,选择“Python”,表达式框内输入:
!shape.area@squarekilometers!。这将使用几何对象的area属性,并以平方千米为单位计算。
4.2 空间关系特征构造
描述一个要素与其周边环境的关系。
- 缓冲区分析:计算每个要素周围一定距离内的区域。例如,计算每个商店500米缓冲区内的居民点数量。
- 工具:“缓冲区”工具。
- 生成特征:缓冲距离本身可作为特征,或者将缓冲区与其他图层叠加进行统计(见下一点)。
- 空间连接:将一个图层的属性连接到另一个图层,基于空间关系(相交、包含、最近)。
- 工具:“空间连接”工具。
- 示例:将人口普查区块(面)的人口密度属性,连接到其中的犯罪事件点(点)上。这样每个犯罪点就拥有了所在区块的人口密度特征。
- 关键设置:匹配选项选择“INTERSECT”(相交)或“WITHIN”(内部)。
- 近邻分析:计算每个要素到另一个图层中最近要素的距离。
- 工具:“近邻分析”工具。
- 生成特征:输出字段
NEAR_DIST即为最近距离,是一个强大的特征。例如,建筑物到最近消防站的距离。
- 密度计算:计算点或线要素在单位面积内的密度(核密度估计)。
- 工具:“核密度分析”工具。
- 生成特征:输出的栅格图层,其像元值即为密度。可以将该栅格值提取到点要素上作为特征(使用“提取多值至点”工具)。
4.3 属性特征变换与编码
对属性表中的原始字段进行处理。
- 标准化/归一化:当特征量纲不同时(如面积是数万,人口密度是小数),必须进行缩放。这通常在导出数据后,在 Python 中使用
sklearn.preprocessing.StandardScaler或MinMaxScaler完成。但在 ArcGIS Pro 中可以先通过字段计算进行初步处理(如取对数)。 - 类别变量编码:将文本型类别(如城市类型:“大城市”、“中等城市”、“小城市”)转换为数值。
- 有序编码:如果类别有顺序,可手动映射为1,2,3。
- 独热编码:如果类别无顺序,需要创建多个二进制字段。这通常在 Python 中用
pd.get_dummies()处理更便捷。在 ArcGIS Pro 中,可以先用“频数”工具查看唯一值,再通过多个“计算字段”步骤创建。
5. 创建机器学习样本与处理栅格数据
5.1 从矢量数据创建样本
假设我们有一个面图层(如土地利用类型),我们需要创建样本点来训练一个分类模型。
- 创建随机点:使用“创建随机点”工具,在研究区域范围内生成一定数量的随机点。
- 提取值到点:使用“多值提取至点”工具,将作为特征的各种栅格图层(如高程栅格、植被指数栅格)的值提取到这些随机点上。
- 添加标签:如果这些点需要标注类别(如实地调查的土地利用类型),可以手动编辑属性表,或通过空间连接从已有的分类面图层获取标签。
5.2 栅格数据处理与“重心迁移”模型准备
搜索词中提到了“有栅格图怎么做重心迁移模型分析”。这通常指分析某个现象(如人口、经济)的空间重心随时间的变化轨迹。
- 数据准备:你需要同一区域、不同时间点的多幅栅格图(例如,1990、2000、2010年的人口密度栅格)。确保它们具有相同的范围、像元大小和坐标系。可以使用“裁剪”和“重采样”工具进行统一。
- 计算重心:对于每一年的栅格,其重心坐标 (Xc, Yc) 可以通过加权平均计算,权重是每个像元的属性值(如人口数)。
- 公式(概念):
Xc = Σ(Value_i * X_i) / Σ(Value_i)Yc = Σ(Value_i * Y_i) / Σ(Value_i)- 其中,
Value_i是第 i 个像元的值,(X_i, Y_i)是该像元的中心点坐标。
- 在 ArcGIS Pro 中的实现:
- 使用“栅格转点”工具,将栅格转换为点要素。每个点具有原始栅格值 (
grid_code) 和坐标。 - 使用“计算字段”添加两个新字段
WeightedX和WeightedY。WeightedX = !grid_code! * !shape.extent.XMin! + !shape.extent.width! / 2(计算像元中心X)WeightedY = !grid_code! * !shape.extent.YMin! + !shape.extent.height! / 2(计算像元中心Y)- 注意:更精确的做法是直接使用
!shape.centroid.X!和!shape.centroid.Y!获取点坐标。
- 右键点击图层,打开“属性表”,查看“统计”信息,分别对
grid_code、WeightedX、WeightedY字段求和。 - 手动计算:
Xc = Sum(WeightedX) / Sum(grid_code),Yc = Sum(WeightedY) / Sum(grid_code)。
- 使用“栅格转点”工具,将栅格转换为点要素。每个点具有原始栅格值 (
- 公式(概念):
- 自动化与建模:上述过程可以通过 Python 脚本循环处理多个年份的栅格,将计算出的重心坐标保存为新的点要素类,从而形成“重心迁移”轨迹。这个轨迹点图层本身就可以作为空间模式分析的对象,或者作为特征输入到其他模型中。
5.3 样本划分与空间交叉验证
重要警告:由于空间自相关(相近位置的特征相似),传统的随机划分训练集/测试集会导致严重的数据泄漏——模型在测试集上表现很好,仅仅因为它“见过”旁边位置的数据。
解决方案:空间交叉验证
- 空间分块:将研究区域划分为若干空间块(如网格、行政区划)。
- 按块划分:确保属于同一空间块的所有样本,要么全在训练集,要么全在测试集。这样能更真实地评估模型预测新区域的能力。
- 工具:可以手动创建网格面(“创建渔网”工具),然后使用“空间连接”为每个样本点分配其所属的网格ID。最后在 Python 中,使用
sklearn.model_selection.GroupKFold并以网格ID作为分组参数进行交叉验证。
6. 数据导出与后续机器学习流程衔接
预处理完成后,需要将数据从 ArcGIS Pro 的环境中导出,供 Python 机器学习库使用。
6.1 导出为表格格式
- 导出属性表:右键点击要素图层,选择“数据” -> “导出表格”。保存为 CSV 格式。
- 关键步骤:确保导出的 CSV 包含了所有构造好的特征字段,以及作为预测目标的标签字段(如果有)。
6.2 在 Python 中读取与处理
在 Jupyter Notebook 或 Python 脚本中:
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split, GroupKFold from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.impute import SimpleImputer # 1. 读取数据 df = pd.read_csv(r‘C:\YourData\processed_samples.csv‘) # 2. 分离特征 (X) 和标签 (y) # 假设 ‘LandUseType‘ 是我们要预测的标签 X = df.drop(columns=[‘LandUseType‘, ‘SampleID‘, ‘BlockID‘]) # 去掉标签和ID列 y = df[‘LandUseType‘] # 3. 处理缺失值(如果在ArcGIS中未完全处理) imputer = SimpleImputer(strategy=‘median‘) # 用中位数填充数值特征 X_numeric = imputer.fit_transform(X.select_dtypes(include=[np.number])) # 4. 标准化数值特征 scaler = StandardScaler() X_scaled = scaler.fit_transform(X_numeric) # 5. 编码类别特征(如果有) # encoder = OneHotEncoder(sparse_output=False, handle_unknown=‘ignore‘) # X_categorical = encoder.fit_transform(X.select_dtypes(include=[‘object‘])) # 将处理后的数值和类别特征合并... # 6. 考虑空间自相关的数据集划分 groups = df[‘BlockID‘] # 之前分配的空间块ID gkf = GroupKFold(n_splits=5) for train_index, test_index in gkf.split(X_scaled, y, groups=groups): X_train, X_test = X_scaled[train_index], X_scaled[test_index] y_train, y_test = y[train_index], y[test_index] # 在此折上进行模型训练和评估7. 常见问题排查与最佳实践
7.1 常见问题排查表
| 问题现象 | 可能原因 | 检查与解决步骤 |
|---|---|---|
| 工具运行失败,报坐标系错误 | 输入数据坐标系未定义或不一致 | 1. 检查所有输入图层的坐标系属性。 2. 使用“定义投影”工具为无坐标系数据定义正确坐标系。 3. 使用“投影”工具统一坐标系。 |
| 空间连接后结果为空 | 空间关系匹配条件设置错误或要素间无交集 | 1. 检查“匹配选项”是否合适(如想包含点,应用“INTERSECT”而非“WITHIN”)。 2. 放大视图,检查两个图层在空间上是否真的有重叠。 |
| 导出的 CSV 在 Python 中读取为乱码或坐标错误 | 编码问题或字段类型问题 | 1. 在 ArcGIS Pro 导出时,选择“UTF-8”编码。 2. 在 Python 中指定编码: pd.read_csv(..., encoding=‘utf-8‘)。3. 检查坐标字段是否被正确识别为数值型(float)。 |
| 模型在训练集上表现好,在测试集上极差 | 空间数据泄漏(训练和测试样本空间相邻) | 采用空间交叉验证,确保训练集和测试集在空间上是分离的。 |
| 栅格计算(如重心)结果明显偏离 | 栅格像元值包含 NoData 或异常值 | 1. 使用“设为空函数”或“重分类”工具处理 NoData 和异常值。 2. 在计算前,检查栅格统计信息(最小值、最大值、均值)。 |
7.2 最佳实践清单
- 始于清晰的业务问题:预处理的所有步骤都应与最终要解决的机器学习问题(分类、回归、聚类)紧密相关。避免构造无关特征。
- 建立可复现的流程:尽量使用 Python 脚本 (
arcpy) 记录所有预处理步骤,而不是完全依赖手动点击。这便于追溯、修改和分享。 - 版本化管理数据:对原始数据、中间处理数据和最终样本数据做好版本标记。可以使用不同的文件地理数据库或文件夹结构来区分。
- 可视化检查每一步:在关键预处理步骤(如投影、空间连接、缓冲区分析)后,将结果加载到地图中,直观检查是否正确。人的空间直觉是强大的调试工具。
- 理解工具参数:不要盲目使用默认参数。例如,缓冲区分析的“融合类型”、重采样时的“重采样技术”,都会对结果产生重大影响。查阅工具帮助文档。
- 特征可解释性:构造的特征应具有明确的物理或业务意义。这不仅能提升模型的可信度,也有助于在模型表现不佳时进行诊断。
- 性能考量:处理大规模栅格或海量矢量时,操作可能非常耗时。考虑使用“影像分析”窗格进行栅格链式处理,或使用
arcpy的并行处理参数 (parallelProcessingFactor)。
空间数据预处理是连接 GIS 世界与机器学习算法的桥梁,其质量直接决定了模型性能的上限。一个稳健的预处理流程,需要兼顾空间数据的特殊性(坐标系、拓扑、自相关)和机器学习数据的通用要求(完整性、一致性、无量纲)。通过 ArcGIS Pro 强大的空间分析工具与 Python 灵活的数据处理能力相结合,我们可以系统化、自动化地完成这项任务,为构建可靠的空间预测与分类模型打下坚实基础。下一步,你可以尝试将处理好的数据接入更复杂的模型(如随机森林、梯度提升树甚至深度学习模型),并持续迭代特征工程,以追求更高的模型性能。