ArcPy 批量投影转换:用 Python 统一文件夹内 Shapefile 坐标系
问题场景:一堆 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 不明 | 跳过,人工核实 |
批处理质量检查
- 记录每个输入文件的原始 CRS。
- 记录跳过的 Unknown 文件。
- 输出后抽样加载,检查与权威底图或控制数据是否重合。
- 比较转换前后要素数量,确认没有文件丢失。
项目避坑:日志比脚本本身更重要
批量处理最怕“悄悄失败”。建议把成功、跳过、报错分别写入日志文件,交付时连同脚本一起保存。
这样几个月后追溯数据来源时,可以清楚知道哪些文件转换过,哪些文件因为坐标系不明被排除。
FAQ
Unknown 坐标系能不能直接定义成目标坐标系?
不能。只有确认它原本就是目标坐标系时,才能定义。否则会制造错误坐标。
Shapefile 投影后字段会变吗?
Project 主要改变几何坐标,属性一般保留。但 Shapefile 字段名和编码限制仍需注意。
批量转换后为何有些图层仍偏移?
可能是源 CRS 定义错误、缺少地理变换参数,或原始数据质量问题。
总结
ArcPy 批量投影转换的重点是“可控”。明确坐标系再转换,未知数据先跳过,执行过程留日志。这样整理出的数据才适合继续入库、分析和制图。