用途
GeoPandas 扩展了 pandas,使其能够对几何类型执行空间操作。它结合了 pandas 和 shapely 的能力,用于地理空间数据分析,处理包括 Shapefile、GeoJSON 和 GeoPackage 文件在内的地理空间矢量数据。
安装
uv pip install geopandas
可选依赖:
# 交互式地图
uv pip install folium
# 地图分类方案
uv pip install mapclassify
# 更快的 I/O 操作(2-4 倍加速)
uv pip install pyarrow
# PostGIS 数据库支持
uv pip install psycopg2
uv pip install geoalchemy2
# 底图
uv pip install contextily
# 制图投影
uv pip install cartopy
快速开始
import geopandas as gpd
# 读取空间数据
gdf = gpd.read_file("data.geojson")
# 基本探索
print(gdf.head())
print(gdf.crs)
print(gdf.geometry.geom_type)
# 简单绘图
gdf.plot()
# 重投影到不同 CRS
gdf_projected = gdf.to_crs("EPSG:3857")
# 计算面积(使用投影 CRS 以保证精度)
gdf_projected['area'] = gdf_projected.geometry.area
# 保存到文件
gdf.to_file("output.gpkg")
核心概念
数据结构
- GeoSeries:带有空间操作的几何向量
- GeoDataFrame:带有几何列的表格式数据结构
读写数据
GeoPandas 可读写多种格式:Shapefile、GeoJSON、GeoPackage、PostGIS、Parquet。
# 带过滤读取
gdf = gpd.read_file("data.gpkg", bbox=(xmin, ymin, xmax, ymax))
# 使用 Arrow 加速写入
gdf.to_file("output.gpkg", use_arrow=True)
坐标参考系
始终检查和管理 CRS 以确保空间操作准确:
# 检查 CRS
print(gdf.crs)
# 重投影(转换坐标)
gdf_projected = gdf.to_crs("EPSG:3857")
# 设置 CRS(仅在元数据缺失时)
gdf = gdf.set_crs("EPSG:4326")
常见操作
几何操作
缓冲、简化、质心、凸包、仿射变换:
# 缓冲 10 个单位
buffered = gdf.geometry.buffer(10)
# 按容差简化
simplified = gdf.geometry.simplify(tolerance=5, preserve_topology=True)
# 获取质心
centroids = gdf.geometry.centroid
空间分析
空间连接、叠加操作、融合:
# 空间连接(相交)
joined = gpd.sjoin(gdf1, gdf2, predicate='intersects')
# 最近邻连接
nearest = gpd.sjoin_nearest(gdf1, gdf2, max_distance=1000)
# 叠加相交
intersection = gpd.overlay(gdf1, gdf2, how='intersection')
# 按属性融合
dissolved = gdf.dissolve(by='region', aggfunc='sum')
可视化
创建静态和交互式地图:
# 分级统计图
gdf.plot(column='population', cmap='YlOrRd', legend=True)
# 交互式地图
gdf.explore(column='population', legend=True).save('map.html')
# 多图层地图
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
gdf1.plot(ax=ax, color='blue')
gdf2.plot(ax=ax, color='red')
常见工作流
加载、转换、分析、导出
# 1. 加载数据
gdf = gpd.read_file("data.shp")
# 2. 检查并转换 CRS
print(gdf.crs)
gdf = gdf.to_crs("EPSG:3857")
# 3. 执行分析
gdf['area'] = gdf.geometry.area
buffered = gdf.copy()
buffered['geometry'] = gdf.geometry.buffer(100)
# 4. 导出结果
gdf.to_file("results.gpkg", layer='original')
buffered.to_file("results.gpkg", layer='buffered')
空间连接与聚合
# 将点连接到多边形
points_in_polygons = gpd.sjoin(points_gdf, polygons_gdf, predicate='within')
# 按多边形聚合
aggregated = points_in_polygons.groupby('index_right').agg({
'value': 'sum',
'count': 'size'
})
# 合并回多边形
result = polygons_gdf.merge(aggregated, left_index=True, right_index=True)
多源数据整合
# 从不同来源读取
roads = gpd.read_file("roads.shp")
buildings = gpd.read_file("buildings.geojson")
parcels = gpd.read_postgis("SELECT * FROM parcels", con=engine, geom_col='geom')
# 确保 CRS 匹配
buildings = buildings.to_crs(roads.crs)
parcels = parcels.to_crs(roads.crs)
# 执行空间操作
buildings_near_roads = buildings[buildings.geometry.distance(roads.union_all()) < 50]
性能提示
- 使用空间索引:GeoPandas 在大多数操作中自动创建空间索引
- 读取时过滤:使用 bbox、mask 或 where 参数仅加载所需数据
- 使用 Arrow 进行 I/O:添加 use_arrow=True 可实现 2-4 倍更快的读写
- 简化几何:当精度不重要时,使用 .simplify() 降低复杂度
- 批量操作:向量化操作比逐行迭代快得多
- 使用合适的 CRS:投影 CRS 用于面积/距离,地理 CRS 用于可视化
最佳实践
- 空间操作前始终检查 CRS
- 面积和距离计算使用投影 CRS
- 空间连接或叠加前匹配 CRS
- 操作前使用 .is_valid 验证几何
- 修改几何列时使用 .copy() 避免副作用
- 分析时简化保留拓扑
- 现代工作流使用 GeoPackage 格式(优于 Shapefile)
- 在 sjoin_nearest 中设置 max_distance 以获得更好性能