上周我用 Cursor 帮我写了个面积统计脚本,跑完一看结果——差了 10 倍。

查了半天,发现是坐标系的问题。AI 生成的代码没问题,但它不懂“空间思维”,有些坑它不会主动提醒你。

今天把这次翻车经历拆开讲,顺便总结几个 AI 做 GIS 时的高频坑。

一、事情经过

起因

我统计各地块的面积,按地类汇总输出 Excel。

文件打开看了一眼:

坐标系:GCS_WGS_1984(地理坐标系)

要素数量:2,856 个

范围:112.3°E ~ 112.8°E, 37.4°N ~ 37.9°N

太原市周边的数据,坐标系是 WGS84 地理坐标。

我让 AI 写的代码

直接把需求丢给 Cursor:

帮我写一个 Python 脚本:

1. 读取 Shapefile

2. 计算每个要素的面积

3. 按地类字段(DLBM)汇总面积

4. 输出到 Excel

Cursor 3 秒就给了代码:

import geopandas as gpd

import pandas as pd

# 读取数据

gdf = gpd.read_file(“地块.shp”)

# 计算面积

gdf[“面积”] = gdf.geometry.area

# 按地类汇总

summary = gdf.groupby(“DLBM”)[“面积”].sum().reset_index()

summary.columns = [“地类代码”, “面积”]

# 输出

summary.to_excel(“面积统计.xlsx”, index=False)

print(“完成!”)

代码看起来没问题,我直接跑了。

结果

输出 Excel 一看:

地类代码

面积

01

0.000312

02

0.000458

03

0.000291

...

...

面积全是 0.000x 这种小数。

我愣了一下——甲方说这块区域大概 50 平方公里,怎么加起来才 0.00x?

二、排查过程

第一反应:单位问题?

我看了一眼数据,坐标系是 WGS84,单位是度。

`geometry.area` 算出来的是平方度,不是平方米。

但平方度怎么换算?我查了一下:

1 度 ≈ 111 km(赤道)

1 平方度 ≈ 12,321 平方公里

那我这个 0.003 平方度,换算成平方公里应该是:

0.003 × 12,321 ≈ 37 平方公里

好像对上了?

不对,这个换算只在赤道成立。

真正的问题:纬度修正

地球是椭球,经度 1 度对应的实际距离,随纬度变化:

经度 1 度 ≈ 111 km × cos(纬度)

太原纬度约 37.5°,cos(37.5°) ≈ 0.79。

所以在这个纬度:

1 平方度 ≈ 111 × 111 × 0.79 ≈ 9,700 平方公里

但这个换算太粗糙了,真正准确的做法是投影到平面坐标系。

正确做法

import geopandas as gpd

gdf = gpd.read_file(“地块.shp”)

# 关键一步:投影到平面坐标系

# 太原在 UTM 49N 区,EPSG:32649

gdf_proj = gdf.to_crs(epsg=32649)

# 现在面积单位是平方米

gdf_proj[“面积_平方米”] = gdf_proj.geometry.area

# 换算成公顷

gdf_proj[“面积_公顷”] = gdf_proj[“面积_平方米”] / 10000

# 汇总

summary = gdf_proj.groupby(“DLBM”)[“面积_公顷”].sum().reset_index()

投影之后,面积单位才是米,结果才准确。

三、AI 为什么没提醒我?

我回头问 Cursor:

“你为什么不提醒我要先投影?”

它回答:

“抱歉,你的需求里没有提到坐标系,我假设数据已经是合适的坐标系。”

问题就在这里。

AI 懂 Python,懂 geopandas 语法,但它不懂 GIS 的空间思维。

它不知道:

- 地理坐标系的单位是度,不能直接算面积

- 不同纬度,1 度对应的实际距离不同

- 面积/距离计算,必须用投影坐标系

这些是 GIS 的领域知识,不是编程知识。AI 没学过。

四、AI 做 GIS 的 9 个高频坑

这次翻车之后,我总结了 AI 容易踩的 9 个坑。实际上这些坑,我们在用传统方法的时候也会犯,但传统方法直面数据结构和属性,能够直观地找到错误本身;用 AI 后,这些问题就会被掩盖,不仔细认真很难发现:

坑 1:坐标系不检查

表现:AI 直接对地理坐标系做面积/距离计算

后果:结果单位是“平方度”或“度”,数值差 10~100 倍

正确做法:

# 先检查坐标系

print(gdf.crs)  # 看一眼是地理坐标还是投影坐标

# 如果是地理坐标(EPSG:4326),先投影

if gdf.crs.to_epsg() == 4326:

    gdf = gdf.to_crs(epsg=合适的目标坐标系)

坑 2:投影坐标系选错

表现:AI 随便选一个投影,比如全用 UTM,不管数据在哪

后果:投影变形大,面积/距离不准

正确做法:

- 中国境内:用 CGCS2000 投影(如 EPSG:4547 是 3°带第 47 区)

- 或者根据数据范围自动选 UTM 区:

from pyproj import CRS

# 根据中心经度选 UTM 区

lon = gdf.geometry.centroid.x.mean()

utm_zone = int((lon + 180) / 6) + 1

utm_epsg = 32600 + utm_zone  # 北半球

坑 3:Shapefile 字段名截断

表现:AI 用中文字段名,或字段名超过 10 字符

后果:导出 Shapefile 时字段名被截断,数据丢失

正确做法:

# 导出前检查字段名长度

for col in gdf.columns:

    if len(col) > 10:

        print(f“警告:字段 {col} 超过 10 字符,将被截断”)

# 用英文字段名

gdf = gdf.rename(columns={“地类代码”: “DLBM”, “面积”: “AREA”})

坑 4:几何有效性不检查

表现:AI 直接做叠加分析,不检查几何是否有效

后果:报错 `TopologyException`,或者结果有空洞

正确做法:

# 检查几何有效性

invalid = gdf[~gdf.geometry.is_valid]

if len(invalid) > 0:

    print(f“发现 {len(invalid)} 个无效几何,正在修复...”)

    gdf.geometry = gdf.geometry.make_valid()

坑 5:大文件直接读进内存

表现:AI 用 `gpd.read_file()` 读几 GB 的文件

后果:内存爆掉,程序崩溃

正确做法:

- 用分块读取:`gpd.read_file(..., rows=10000)`

- 或用 arcpy 的游标:`arcpy.da.SearchCursor`

- 或转成 GeoPackage 分层存储

坑 6:坐标顺序搞反(经度/纬度 vs 纬度/经度)

表现:AI 写 `Point(lat, lon)` 或 `Point(y, x)`,顺序反了

后果:点跑到地球另一边,或者报错“坐标超出范围”

正确做法:

# GeoPandas / Shapely 标准顺序:经度在前,纬度在后

from shapely.geometry import Point

# 正确:经度在前(x, y)

point = Point(112.5, 37.8)  # 太原附近

# 错误:纬度在前

# point = Point(37.8, 112.5)  # 跑到别的地方了

# 检查:坐标是否在合理范围

lon, lat = point.x, point.y

if not (-180 <= lon <= 180 and -90 <= lat <= 90):

    print(“警告:坐标可能反了!”)

我踩过一次:200 个点,经纬度列反了,结果全跑到太平洋里去了。

坑 7:高德/百度坐标直接叠加标准底图

表现:AI 用高德 POI 坐标直接叠加到 OSM/天地图底图

后果:点位偏移几百米,看起来“对不上”

原因:高德/百度用的是 GCJ-02/BD-09 坐标系,不是 WGS84

正确做法:

# 需要手动实现坐标转换函数

import math

def gcj02_to_wgs84(lon, lat):

    """GCJ-02 转换为 WGS84"""

    a = 6378245.0  # 长半轴

    ee = 0.00669342162296594323  # 偏心率平方

    if _out_of_china(lon, lat):

        return lon, lat

    dlat = _transform_lat(lon - 105.0, lat - 35.0)

    dlon = _transform_lon(lon - 105.0, lat - 35.0)

    radlat = lat / 180.0 * math.pi

    magic = math.sin(radlat)

    magic = 1 - ee * magic * magic

    sqrtmagic = math.sqrt(magic)

    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * math.pi)

    dlon = (dlon * 180.0) / (a / sqrtmagic * math.cos(radlat) * math.pi)

    return lon - dlon, lat - dlat

# 使用

wgs_lon, wgs_lat = gcj02_to_wgs84(gcj_lon, gcj_lat)

# 然后才能叠加到标准底图

gdf = gpd.GeoDataFrame(

    df,

    geometry=gpd.points_from_xy(df[“wgs_lon”], df[“wgs_lat”]),

    crs=“EPSG:4326”

)

提醒:国内地图服务分三派——

- 天地图/OSM:WGS84

- 高德/腾讯:GCJ-02

- 百度:BD-09

混用之前必须转换。

坑 8:缓冲区距离单位搞错

表现:AI 写 `gdf.buffer(1000)`,以为生成 1 公里缓冲区

后果:如果数据是地理坐标系,参数单位是“度”而不是“米”,生成的缓冲区和你想的完全不一样

正确做法:

# 先确认坐标系单位

print(gdf.crs.axis_info[0].unit_name)  # “degree” 还是 “metre”

# 如果是地理坐标,先投影

gdf_proj = gdf.to_crs(epsg=32649)  # 投影后单位是米

# 再做缓冲区

buffer = gdf_proj.buffer(1000)  # 1000 米 = 1 公里

我踩过一次:做“河流 500 米缓冲区”,忘了看坐标系单位,数据是 WGS84 地理坐标——结果生成的不是 500 米的缓冲区,偏差极大。

坑 9:ArcGIS Pro 和 ArcMap 的 API 混用

表现:AI 用 `arcpy.mapping`(ArcMap API),但你用的是 ArcGIS Pro

后果:报错 `AttributeError: module 'arcpy' has no attribute 'mapping'`

原因:ArcGIS Pro 用 `arcpy.mp`(新 API),ArcMap 用 `arcpy.mapping`(旧 API)

正确做法:

# ArcGIS Pro(3.x)

import arcpy.mp as mp  # 注意是 mp 不是 mapping

aprx = mp.ArcGISProject("CURRENT")

m = aprx.listMaps()[0]

lyr = m.listLayers()[0]

# ArcMap(10.x)— 已过时

# import arcpy.mapping as mapping

# mxd = mapping.MapDocument("CURRENT")

提醒:告诉 AI 你用的是 ArcGIS Pro 3.x,别让它生成 ArcMap 的代码。

五、怎么避免这些坑?

方法 1:把领域知识写进 Skill

我现在用 WorkBuddy,把 GIS 的坑都写进了 `gis-assistant` Skill 里:

## 数据质量检查(分析前必做)

- 坐标系是否定义?地理坐标不能直接算面积

- 几何是否有效?无效几何会导致分析失败

- 字段名是否超长?Shapefile 限 10 字符

- 编码是否正确?GBK/UTF-8 乱码问题

AI 加载这个 Skill 之后,每次分析前会自动提醒我检查这些项。

方法 2:建立检查清单

每次拿到数据,先跑一遍:

def quick_check(gdf):

    print(f“坐标系: {gdf.crs}”)

    print(f“是否地理坐标: {gdf.crs.is_geographic}”)

    print(f“要素数量: {len(gdf)}”)

    print(f“无效几何: {(~gdf.geometry.is_valid).sum()}”)

    print(f“字段名超长: {sum(len(c)>10 for c in gdf.columns)}”)

跑完再决定用什么分析方法。

方法 3:让 AI 解释代码

拿到 AI 生成的代码,多问一句:

“这段代码在什么情况下会出错?”

或者:

“坐标系是 WGS84 时,这个计算结果是什么单位?”

逼 AI 去思考领域问题,而不是只给语法正确的代码。

六、这次翻车的教训

1. AI 懂编程,不懂 GIS——语法正确 ≠ 结果正确

2. 坐标系是 GIS 的命根子——面积/距离计算前必须确认

3. 领域知识要固化——写进 Skill,让 AI 每次都带着

4. 结果要校验——算出来先看数量级对不对,别直接交

5. 坑会重复出现——踩过的坑要记下来,形成检查清单

现在我用 AI 做 GIS,第一件事就是让 AI 先跑一遍数据质量检查,再开始分析。

多花 1 分钟检查,少花 1 小时排查。

写在最后

AI 确实能大幅提升效率,但在刚开始用于分析空间数据时,它还不是 GIS 专家,需要多轮对话,确定他的工作程度,从简单任务到复杂任务,训练其逐渐成为专家,就像咱们刚开始接触空间地理信息数据一样,逐步形成空间分析的逻辑闭环。

它不知道“1 度在赤道和北极不一样长”,不知道“面积计算必须用投影坐标”,不知道“Shapefile 字段名会截断”——这些是你才知道的事。

AI 是工具,核心还是人。

把你的领域知识教给它,它才能真的帮上忙。

互动:

你用 AI 做 GIS 时踩过什么坑?评论区说说,看看谁的最离谱。

【GIS与AI】深度了解GIS+AI 实战经验、源码模板、避坑指南

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐