2、GIS基础概念:地理坐标系、投影坐标系、矢量数据与栅格数据、空间参考与拓扑

在进入Python与GIS的实战之前,必须先建立一套清晰的空间数据认知框架。很多初学者在读取Shapefile或GeoTIFF时,往往只关注属性表或像素值,却忽略了数据最底层的“空间骨架”——坐标系、数据模型与拓扑规则。如果这些基础概念不牢固,后续的缓冲区分析、叠加分析、地图叠加显示都会出现“错位”或“变形”的严重问题。本章将围绕四个核心支柱展开:地理坐标系与投影坐标系的本质区别、矢量与栅格两种数据模型的适用场景、空间参考的完整组成,以及拓扑规则如何保障空间数据的逻辑一致性。

GIS空间数据基础概念关系图 空间数据基础 地理坐标系 (GCS) 以经纬度定位,单位:度 参考椭球体 + 大地基准面 如 WGS84, CGCS2000 投影坐标系 (PCS) 基于GCS,通过数学变换 单位:米(常用) 如 UTM, Web Mercator 数据模型 矢量:点/线/面,离散对象 栅格:像元矩阵,连续表面 选择依据:分析类型与精度 空间参考与拓扑 空间参考 = GCS + PCS + 分辨率 拓扑:邻接/连通/包含规则 保证数据逻辑一致性 图:GIS四大基础概念之间的支撑与关联关系

上图展示了本章四个核心概念之间的逻辑关系:地理坐标系是投影坐标系的基础,而空间参考则是两者的综合封装;矢量与栅格是两种不同的空间数据表达方式,它们都必须依附于某个空间参考才能被正确解析。下面我们逐一深入拆解。

2.1 地理坐标系:地球的“经纬度骨架”

核心原理

地理坐标系(Geographic Coordinate System, GCS)是用三维球面来定义地球表面位置的一种坐标系。它使用经度(Longitude)和纬度(Latitude)两个角度值来定位,单位是十进制度(Decimal Degrees)。GCS的构成包含三个关键要素:参考椭球体(Ellipsoid)、大地基准面(Datum)和本初子午线(Prime Meridian)。参考椭球体是对地球不规则形状的数学近似,常见的有WGS84椭球、CGCS2000椭球等;大地基准面则定义了椭球体相对于地球质心的位置和方向,例如WGS84基准面、NAD83基准面。简单来说,椭球体是“形状”,基准面是“位置校准”。

判断方法与操作流程

在Python的GeoPandas库中,你可以通过以下方式快速查看一个矢量数据的地理坐标系:

import geopandas as gpd
gdf = gpd.read_file('cities.shp')
print(gdf.crs)  # 输出类似 EPSG:4326 (WGS84)
# 判断是否为地理坐标系
print(gdf.crs.is_geographic)  # 返回 True 或 False

如果返回的crs是EPSG:4326或EPSG:4490(CGCS2000),说明数据是地理坐标系。此时若直接测量面积或距离,得到的结果单位是度,无法用于实际工程计算。

案例拆解:全球城市坐标的读取

假设你从公开数据源下载了一份全球主要城市的CSV文件,其中经纬度字段是十进制度。你使用GeoPandas创建点数据时,必须显式声明其坐标系为WGS84:

from shapely.geometry import Point
import pandas as pd
import geopandas as gpd

df = pd.read_csv('world_cities.csv')
geometry = [Point(x, y) for x, y in zip(df['lng'], df['lat'])]
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs='EPSG:4326')

如果不声明crs,后续任何空间操作(如缓冲区、叠加)都会因缺少坐标参考而报错或产生错误结果。这是初学者最容易忽略的步骤。

常见误区:很多人认为经纬度就是“平面坐标”,直接拿经纬度计算距离。实际上,1度经度在赤道约111公里,但在高纬度地区会急剧缩短。地理坐标系只适合定位,不适合测量和面积计算。

2.2 投影坐标系:从球面到平面的“变形艺术”

核心原理

投影坐标系(Projected Coordinate System, PCS)是在地理坐标系的基础上,通过数学映射将球面坐标转换为平面直角坐标(X, Y),单位通常是米。投影的本质是变形——没有任何一种投影能同时保持面积、形状、距离和方向完全不变。常见的投影类型包括:等角投影(如Web Mercator,保持形状但面积变形严重)、等积投影(如Albers,保持面积但形状变形)、等距投影(保持特定方向的距离)。

判断方法与操作流程

在Python中,使用PyProj库可以轻松进行坐标系转换:

from pyproj import Transformer
# 从WGS84经纬度转Web Mercator (EPSG:3857)
transformer = Transformer.from_crs("EPSG:4326", "EPSG:3857", always_xy=True)
x, y = transformer.transform(116.4074, 39.9042)  # 北京坐标
print(x, y)  # 输出米制坐标

判断一个数据是否为投影坐标系,可以检查其crs的is_projected属性。中国常用的投影坐标系包括:UTM分区(全球通用)、CGCS2000 / 3-degree Gauss-Kruger(中国国家标准)、Web Mercator(在线地图专用)。

案例拆解:面积计算中的坐标系陷阱

假设你需要计算北京市各行政区的面积。如果数据是WGS84经纬度,直接使用gdf.area得到的结果是“平方度”,毫无意义。正确做法是:

# 先投影到适合北京的等积投影,例如 Albers Equal Area (EPSG: 102025)
gdf_projected = gdf.to_crs('EPSG:102025')
gdf_projected['area_km2'] = gdf_projected.geometry.area / 1e6
print(gdf_projected[['name', 'area_km2']])

这里选择等积投影是为了保证面积计算准确。如果选择Web Mercator,高纬度地区的面积会被严重夸大,导致计算结果失真。

经验提醒:在Python中,to_crs()是矢量数据转换坐标系的常用方法。对于栅格数据,则需要使用rasterio库的reproject()函数,且要注意重采样方法的选择(如双线性、最近邻)。

2.3 矢量数据与栅格数据:两种空间表达模型

核心原理

矢量数据(Vector Data)用点、线、面(Point, Line, Polygon)来精确表达离散地理对象,每个要素可以附带属性信息。其优点是精度高、存储量小、适合网络分析和拓扑分析。栅格数据(Raster Data)则用规则像元(Pixel/Cell)矩阵来表达连续表面或影像,每个像元存储一个数值(如高程、温度、光谱反射率)。其优点是数据结构简单、适合空间插值和地表分析,但精度受分辨率限制。

选择判断流程

维度矢量数据栅格数据
空间表达离散对象(道路、地块)连续表面(DEM、遥感影像)
精度高,边界精确受像元大小限制
存储量相对较小(简单几何)大,与分辨率平方成正比
分析能力拓扑、网络、叠加分析坡度、坡向、水文分析
Python库GeoPandas, ShapelyRasterio, Xarray

案例拆解:洪水淹没分析中的混合使用

在一次洪水风险评估项目中,你拥有:① 河流的矢量线数据(用于提取河道中心线);② 数字高程模型DEM(栅格数据,分辨率30米)。分析流程如下:

  1. 使用rasterio读取DEM,并转换为NumPy数组。
  2. 使用GeoPandas读取河流矢量,并栅格化(Rasterize)为与DEM相同分辨率的栅格。
  3. 设定水位阈值(如50米),在DEM中标记所有低于阈值的像元为淹没区。
  4. 将淹没区栅格转换为矢量多边形,以便与行政区划叠加统计受灾人口。

这个案例中,矢量数据提供了精确的河流位置,栅格数据提供了连续的地表高程,两者结合才能完成完整的分析。在Python中,栅格转矢量可以使用rasterio.features.shapes(),矢量转栅格可以使用rasterio.features.rasterize()。

总结复盘:选择数据模型时,先问自己:分析对象是离散实体还是连续场?如果要做路径规划,选矢量;如果要做坡度分析,选栅格。不要盲目混用,但也要掌握两者互转的技能。

2.4 空间参考与拓扑:数据一致性的“守护者”

核心原理

空间参考(Spatial Reference)是一个综合概念,它包含了坐标系(GCS和PCS)、分辨率(Resolution)和容差(Tolerance)。在Python中,GeoPandas的crs属性就是空间参考的简化表示。拓扑(Topology)则是研究空间实体之间关系(邻接、连通、包含、相交)的规则集合。拓扑关系不随坐标变换而改变,例如“A多边形与B多边形相邻”这一事实,无论坐标系如何转换都成立。

操作流程:拓扑检查与修复

在GIS分析中,常见的拓扑错误包括:多边形重叠(Overlap)、缝隙(Gap)、未闭合线(Unclosed Line)等。使用Python的shapely库可以进行基础检查:

from shapely.geometry import Polygon
from shapely.validation import explain_validity

# 创建一个有重叠的多边形
poly1 = Polygon([(0,0), (2,0), (2,2), (0,2)])
poly2 = Polygon([(1,1), (3,1), (3,3), (1,3)])
print(poly1.intersects(poly2))  # True,存在重叠

# 检查多边形是否有效
print(explain_validity(poly1))  # Valid Geometry

对于更复杂的拓扑规则(如“面不能重叠”、“线必须在端点处连接”),建议使用PostGIS数据库或ArcGIS的拓扑工具。在Python生态中,geopandas的overlay()函数可以检测并处理重叠,但无法自动修复所有拓扑错误。

案例拆解:行政区划数据的拓扑修复

某项目需要合并两个相邻省份的行政区划数据,但发现边界处存在细小的缝隙和重叠。这些误差会导致后续的“面积汇总”出现重复或遗漏。处理步骤:

  1. 使用gdf.buffer(0)方法消除多边形之间的微小缝隙(注意:buffer(0)可以修复部分无效几何)。
  2. 使用gdf.overlay('union')将重叠区域合并为一个整体。
  3. 使用gdf.geometry = gdf.geometry.buffer(0)再次检查有效性。
  4. 最后,使用gdf.geometry = gdf.geometry.make_valid()(Shapely 2.0+)强制修复所有无效几何。

修复后,重新计算面积,确保与官方统计数字一致。这个案例说明,拓扑错误如果不处理,会直接导致分析结果不可信。

风险提示:在Python中,make_valid()虽然能修复几何,但可能会改变几何的形状(如将自相交多边形拆分为多个多边形)。修复后务必进行可视化检查,确保没有引入新的逻辑错误。

2.5 本章知识结构总览

概念核心组成Python对应操作典型应用
地理坐标系椭球体、基准面、本初子午线gdf.crs查看全球定位、数据采集
投影坐标系投影方法、中央经线、标准纬线gdf.to_crs()面积测量、地图制图
矢量数据点、线、面 + 属性表GeoDataFrame网络分析、地址匹配
栅格数据像元矩阵、波段、分辨率rasterio.open()遥感分类、地形分析
空间参考GCS + PCS + 容差pyproj.Transformer数据集成、坐标转换
拓扑邻接、连通、包含规则shapely谓词数据质量检查、编辑