ArcPy 批量投影转换:用 Python 统一文件夹内 Shapefile 坐标系

ArcPy
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

问题场景:一堆 Shapefile 坐标系不统一怎么办

项目数据汇总时,经常会收到多个部门发来的 Shapefile。有的使用 WGS84,有的使用 CGCS2000,有的缺少 prj 文件,还有的坐标系写着 Unknown。手动逐个投影转换不仅慢,还容易漏掉异常文件。ArcPy 的价值就在于把这个整理过程自动化,并留下可复核日志。

但批量投影转换不能粗暴执行。最危险的情况是:脚本把未知坐标系数据也转换了,表面生成了一批整齐文件,实际位置全错。因此脚本应先识别空间参考,未知数据跳过并记录,确认后再单独处理。

Project 与 Define Projection 不要混用

Define Projection用于给缺失 CRS 的数据补充原始坐标系定义,不改变坐标值。Project用于从一个已知 CRS 转换到另一个 CRS,会改变坐标值。批处理脚本中,只有空间参考明确的数据才应该进入 Project。

基础脚本示例

import arcpy
import os

in_dir = r"D:gisinput_shp"
out_dir = r"D:gisprojected_shp"
target_sr = arcpy.SpatialReference(4490)

os.makedirs(out_dir, exist_ok=True)
arcpy.env.workspace = in_dir
arcpy.env.overwriteOutput = True

for shp in arcpy.ListFeatureClasses("*.shp"):
    desc = arcpy.Describe(shp)
    sr = desc.spatialReference
    if sr.name == "Unknown":
        print("跳过未知坐标系:", shp)
        continue
    out_name = os.path.splitext(shp)[0] + "_cgcs2000.shp"
    arcpy.management.Project(shp, os.path.join(out_dir, out_name), target_sr)
    print("完成:", out_name)

什么时候需要地理变换参数

如果源坐标系和目标坐标系的地理基准不同,例如从西安 1980 或北京 1954 转到 CGCS2000,可能需要 geographic transformation。ArcGIS Pro 工具界面会根据数据范围提示可用转换方法,ArcPy 中也可以把转换名称传给 Project。

数据状态 处理方式
有正确 prj 可直接 Project
无 prj 但原 CRS 已知 先 Define Projection,再 Project
原 CRS 不明 跳过,人工核实

批处理质量检查

  1. 记录每个输入文件的原始 CRS。
  2. 记录跳过的 Unknown 文件。
  3. 输出后抽样加载,检查与权威底图或控制数据是否重合。
  4. 比较转换前后要素数量,确认没有文件丢失。

项目避坑:日志比脚本本身更重要

批量处理最怕“悄悄失败”。建议把成功、跳过、报错分别写入日志文件,交付时连同脚本一起保存。

这样几个月后追溯数据来源时,可以清楚知道哪些文件转换过,哪些文件因为坐标系不明被排除。

FAQ

Unknown 坐标系能不能直接定义成目标坐标系?

不能。只有确认它原本就是目标坐标系时,才能定义。否则会制造错误坐标。

Shapefile 投影后字段会变吗?

Project 主要改变几何坐标,属性一般保留。但 Shapefile 字段名和编码限制仍需注意。

批量转换后为何有些图层仍偏移?

可能是源 CRS 定义错误、缺少地理变换参数,或原始数据质量问题。

总结

ArcPy 批量投影转换的重点是“可控”。明确坐标系再转换,未知数据先跳过,执行过程留日志。这样整理出的数据才适合继续入库、分析和制图。