项目地址: https://github.com/geopandas/geopandas
官方文档: https://geopandas.readthedocs.io
最新版本: 1.2.0(截至 2026-10,PyPI)
许可证: BSD-3-Clause
概述
GeoPandas 是 Python 地理空间矢量数据处理的核心库,在 pandas DataFrame 基础上扩展了几何列支持。核心类 GeoDataFrame(继承 pandas.DataFrame)和 GeoSeries(继承 pandas.Series)通过 Shapely 提供几何运算、通过 pyproj 提供坐标系管理、通过 pyogrio/fiona 提供文件 IO。
环境准备
bash# Conda / Mamba(推荐,自动处理 GEOS/PROJ/GDAL 二进制依赖) # 推荐使用 conda-forge/miniforge 发行版(比 Anaconda 轻量) conda install -c conda-forge geopandas # pip(各依赖有预编译 wheel 时可独立安装) pip install geopandas # 可选依赖(绘图/交互地图/分类/Parquet 等) pip install "geopandas[all]" # 验证 python -c "import geopandas as gpd; gpd.show_versions()"
环境要求: Python >= 3.11(GeoPandas 1.2 起;1.0 为 >= 3.9)。
依赖关系
| 核心依赖 | 最低版本 | 用途 |
|---|---|---|
pandas | >= 2.2.0 | DataFrame 基类 |
shapely | >= 2.1.0 | 几何对象与运算 (GEOS) |
pyproj | >= 3.7.0 | CRS 处理与坐标变换 |
pyogrio | >= 0.8 | 默认文件 IO 引擎 (GDAL/OGR) |
numpy | >= 2 | 数组运算 |
| 可选依赖 | 用途 |
|---|---|
matplotlib >= 3.9 | 静态地图绘制 .plot() |
folium | 交互式地图 .explore() |
mapclassify >= 2.7 | 分级设色分类方案 |
fiona >= 1.8.21 | 备选文件 IO 引擎 |
pyarrow >= 15.0.0 | Parquet/Feather/Arrow 支持 |
geopy | 地理编码 |
SQLAlchemy >= 2.0 + GeoAlchemy2 | PostGIS 读写 |
xyzservices | 瓦片底图服务 |
全局配置
pythonimport geopandas as gpd gpd.options.display_precision # int|None, WKT 小数位数 (0-16) gpd.options.io_engine # None|"pyogrio"|"fiona"
核心类(GeoSeries/GeoDataFrame)完整 API 参考见 reference/core-api.md
IO 模块
文件读写
pythongpd.read_file(filename, bbox=None, mask=None, columns=None, rows=None, engine=None, **kwargs) gdf.to_file(filename, driver=None, schema=None, index=None, **kwargs) gpd.list_layers(filename) # → DataFrame (layer_name, geometry_type)
支持的文件格式(扩展名 → 驱动):
| 扩展名 | 驱动 |
|---|---|
.shp | ESRI Shapefile |
.json, .geojson | GeoJSON |
.geojsonl, .geojsons | GeoJSONSeq |
.gpkg | GPKG (GeoPackage) |
.gml, .xml | GML |
.gpx | GPX |
.csv | CSV |
.fgb | FlatGeobuf |
.dxf | DXF |
.tab, .mif, .mid | MapInfo File |
引擎选项:"pyogrio"(默认)或 "fiona"。支持所有 GDAL/OGR 驱动。
GeoParquet / Feather
pythongpd.read_parquet(path, columns=None, storage_options=None, bbox=None, **kwargs) gpd.read_feather(path, columns=None, **kwargs) gdf.to_parquet(path, compression="snappy", geometry_encoding="WKB", write_covering_bbox=False, schema_version=None, **kwargs) gdf.to_feather(path, compression=None, schema_version=None, **kwargs)
GeoParquet 规范版本:"1.0.0", "1.1.0" 等。几何编码:"WKB"(默认)、"geoarrow"。
Arrow (GeoArrow)
pythongdf.to_arrow(geometry_encoding="WKB", interleaved=True, include_z=None) GeoDataFrame.from_arrow(table, geometry=None, to_pandas_kwargs=None) gs.to_arrow(geometry_encoding="WKB", interleaved=True, include_z=None) GeoSeries.from_arrow(arr, **kwargs)
PostGIS
pythongpd.read_postgis(sql, con, geom_col="geom", crs=None, index_col=None, ...) gdf.to_postgis(name, con, schema=None, if_exists="fail", index=False, ...)
需要:SQLAlchemy + GeoAlchemy2 + psycopg/psycopg2。
WKB/WKT 与坐标构造
pythongpd.points_from_xy(x, y, z=None, crs=None) # → GeometryArray GeoSeries.from_wkb(data, crs=None, on_invalid="raise") GeoSeries.from_wkt(data, crs=None, on_invalid="raise") GeoSeries.from_xy(x, y, z=None, crs=None)
工具模块 (tools)
空间连接
pythongpd.sjoin(left_df, right_df, how="inner", predicate="intersects", lsuffix="left", rsuffix="right", distance=None, on_attribute=None)
how:"inner","left","right"predicate:"intersects","within","contains","contains_properly","overlaps","crosses","touches","covers","covered_by","dwithin"on_attribute: 附加非空间连接过滤列名
最近邻空间连接
pythongpd.sjoin_nearest(left_df, right_df, how="inner", max_distance=None, distance_col=None, exclusive=False)
空间叠加
pythongpd.overlay(df1, df2, how="intersection", keep_geom_type=None, make_valid=True)
how:"intersection","union","identity","symmetric_difference","difference"
裁剪
pythongpd.clip(gdf, mask, keep_geom_type=False, sort=False)
mask: GeoDataFrame、GeoSeries、(Multi)Polygon 或(minx, miny, maxx, maxy)元组
地理编码
pythongpd.tools.geocode(strings, provider=None, **kwargs) # → GeoDataFrame gpd.tools.reverse_geocode(points, provider=None, **kwargs) # → GeoDataFrame
需要 geopy。默认 provider: "photon"。返回含 geometry 和 address 列的 GeoDataFrame。
其他工具
pythongpd.tools.collect(x, multi=False) # 收集几何体为多部件 gpd.show_versions() # 打印依赖版本信息
可视化
静态绑图 (matplotlib)
python# GeoSeries gs.plot(cmap=None, color=None, ax=None, figsize=None, aspect="auto") # GeoDataFrame — 支持分级设色 gdf.plot(column=None, cmap=None, color=None, ax=None, figsize=None, legend=False, scheme=None, k=5, vmin=None, vmax=None, markersize=None, categories=None, classification_kwds=None, missing_kwds=None, legend_kwds=None, **style_kwds)
scheme 参数需要 mapclassify,支持 "quantiles", "equal_interval", "fisher_jenks" 等分类方案。
1.2 变化: 静态绘图被重写(大部分向后兼容):legend_kwds={"colorbar": True} 可输出连续色带、tiles= 可直接叠加 contextily 底图、add_labels 控制坐标轴单位标签、分类绘图支持字典映射颜色;依赖内部 collections 结构的旧代码可能受影响。
交互式地图 (folium/leaflet)
pythongdf.explore(column=None, cmap=None, color=None, m=None, tiles="OpenStreetMap", tooltip=True, popup=False, categorical=False, legend=True, scheme=None, k=5, marker_type=None, marker_kwds={}, style_kwds={}, tooltip_kwds={}, popup_kwds={}, legend_kwds={}, **kwargs)
典型工作流与常用模式
创建 GeoDataFrame
pythonimport geopandas as gpd from shapely.geometry import Point, Polygon, LineString # 从文件读取 gdf = gpd.read_file("data.shp") gdf = gpd.read_file("data.gpkg", layer="my_layer") gdf = gpd.read_parquet("data.parquet") # 从字典创建 gdf = gpd.GeoDataFrame( {"name": ["A", "B"], "value": [1, 2], "geometry": [Point(0, 0), Point(1, 1)]}, crs="EPSG:4326" ) # 从 pandas DataFrame + 坐标列 import pandas as pd df = pd.DataFrame({"lon": [116.4, 121.5], "lat": [39.9, 31.2], "city": ["北京", "上海"]}) gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.lon, df.lat), crs="EPSG:4326") # 从 WKT/WKB gs = gpd.GeoSeries.from_wkt(["POINT (0 0)", "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))"], crs=4326) # 从 GeoJSON FeatureCollection gdf = gpd.GeoDataFrame.from_features(feature_collection["features"], crs="EPSG:4326")
CRS 操作
pythongdf = gdf.set_crs("EPSG:4326") # 赋值 CRS(数据本身不变) gdf = gdf.to_crs("EPSG:3857") # 投影变换(坐标重算) gdf = gdf.to_crs(epsg=32650) # 按 EPSG 代码投影 utm = gdf.estimate_utm_crs() # 自动检测 UTM 分区
注意:set_crs() 仅标记 CRS 不转换坐标;to_crs() 实际执行坐标变换。面积/距离计算前务必投影到适当的投影坐标系(如 UTM)。
空间分析
python# 空间连接 joined = gpd.sjoin(points_gdf, polygons_gdf, how="inner", predicate="within") # 最近邻连接 nearest = gpd.sjoin_nearest(gdf1, gdf2, max_distance=1000, distance_col="dist_m") # 空间叠加 result = gpd.overlay(gdf1, gdf2, how="intersection") # 裁剪 clipped = gpd.clip(gdf, mask_polygon) clipped = gpd.clip(gdf, (xmin, ymin, xmax, ymax)) # 矩形快速裁剪 # 按属性融合 dissolved = gdf.dissolve(by="province", aggfunc="sum") # 多部件炸开 exploded = gdf.explode(index_parts=False) # 缓冲区、简化 gdf["buffer_100m"] = gdf.geometry.buffer(100) gdf["simplified"] = gdf.geometry.simplify(tolerance=50)
几何谓词与度量
pythongdf.geometry.intersects(other_geom) # Series[bool] gdf.geometry.contains(other_geom) # Series[bool] gdf.geometry.within(other_geom) # Series[bool] gdf.geometry.distance(other_geom) # Series[float] gdf.geometry.area # Series[float] gdf.geometry.length # Series[float] gdf.geometry.centroid # GeoSeries gdf.geometry.bounds # DataFrame gdf.total_bounds # array [minx, miny, maxx, maxy]
数据输出
pythongdf.to_file("output.gpkg", driver="GPKG", layer="result") gdf.to_file("output.geojson", driver="GeoJSON") gdf.to_parquet("output.parquet") geojson_str = gdf.to_json() gdf.to_postgis("table_name", engine, if_exists="replace")
可视化
python# 静态地图 ax = gdf.plot(column="population", cmap="YlOrRd", legend=True, figsize=(12, 8)) # 多图层叠加 ax = base_gdf.plot(color="lightgrey", figsize=(12, 8)) points_gdf.plot(ax=ax, color="red", markersize=5) # 交互式地图 m = gdf.explore(column="population", cmap="viridis", tooltip=["name", "population"], tiles="CartoDB positron")
性能提示
- GeoParquet 比 Shapefile/GeoJSON 读写快 5-10 倍,优先使用
- 空间索引
.sindex自动构建 STRtree,query()和nearest()可大幅加速空间查询 - 矩形裁剪
clip_by_rect()或clip(gdf, (xmin,ymin,xmax,ymax))比多边形裁剪快 pyogrio引擎(默认)比fiona快 2-5 倍- 大数据集用
read_file(rows=slice(0, 1000))先预览 dissolve()使用method="coverage"对已知不重叠的多边形更快- 避免逐行循环几何操作,使用向量化方法(如
buffer(),intersection()等)
常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 面积/距离为 0 或极小 | CRS 为地理坐标系 (度) | gdf.to_crs(gdf.estimate_utm_crs()) 后计算 |
sjoin 无结果 | 两个 GDF 的 CRS 不一致 | 统一 CRS:gdf2 = gdf2.to_crs(gdf1.crs) |
ValueError: GeoDataFrame does not support multiple columns using the geometry column name 'geometry' | 多个列名为 geometry | 重命名冲突列或使用 set_geometry() 指定 |
to_file 属性被截断 | Shapefile 字段名限制 10 字符 | 使用 GeoPackage (.gpkg) 或 GeoJSON |
set_crs vs to_crs 混淆 | set_crs 仅赋值不转换 | 已有 CRS 需要转换用 to_crs();无 CRS 标记用 set_crs() |
| Shapefile 不支持空值/日期时间 | Shapefile 格式限制 | 使用 GeoPackage 格式 |
buffer(resolution=...) 出现弃用警告 | 1.2 起 resolution 被弃用,向 shapely 命名惯例对齐 | 改用 quad_segs 参数 |
DriverError 无法写入 | 驱动不支持或文件被占用 | 检查驱动名拼写、关闭已打开的文件 |
align=True 导致意外 NaN | 二元操作默认按索引对齐 | 传入 align=False 或重置索引 |
AI 使用建议
- 本技能的组织:主文件给高频用法,完整参数表与高级示例在
reference/core-api.md,需要时再展开;示例工程与生成的数据写到工作目录,不要改动技能目录本身。 - 执行环境:命令在终端 / shell 中执行(Windows 用 PowerShell);不要假设
python是 QGIS/GDAL 自带的解释器,先python -c "import sys; print(sys.executable, sys.version)"。 - 先探测版本:
python -c "import geopandas as gpd; print(gpd.__version__, gpd.options.io_engine)";本技能按 1.2.0 / Python >= 3.11 编写,低版本会缺to_arrow、to_parquet(geometry_encoding=...)与 1.2 新绘图参数(tiles=、legend_kwds={"colorbar": True}),回答时说明差异而不是硬写。 - 检查依赖后端:
python -c "import pyogrio, pyproj; print(pyogrio.__version__, pyproj.__version__, pyproj.datadir.get_data_dir())";PROJ 数据目录缺失时to_crs("EPSG:3857")抛CRSError: Invalid projection,装pyproj/pyogrio前先征得用户同意。 - 验证产物(必做):写完立即重开核对,
gdf = gpd.read_file("out.gpkg", layer="result"); print(gdf.crs, len(gdf), gdf.is_valid.all(), gdf.total_bounds),并确认面积/长度是在投影坐标系下算的。 - 落图后看图:
ax = gdf.plot(column="pop", legend=True, figsize=(12, 8)); ax.figure.savefig("map.png", dpi=100)(需 matplotlib),再打开该 PNG 检查范围、图例与空几何(能读图的环境可直接查看截图),不要只凭退出码报告成功。 - 典型误操:
set_crs()只标记不改坐标、to_file()默认整表覆盖、to_postgis(if_exists="replace")会删表重建——执行前确认目标路径/表名,Shapefile 字段名超 10 字符会被截断,改用.gpkg。 - 安全:数据库连接串里的密码不要回显在命令输出里;
pip install geopandas[all]、写入系统目录或覆盖生产数据前先得到用户确认。
相关技能
- shapely — 底层几何计算库:../shapely/SKILL.md
- gdal — 命令行数据处理:../gdal/SKILL.md
- pyqgis — QGIS Python 绑定:../pyqgis/SKILL.md
- postgis — 空间数据库:../postgis/SKILL.md
- geopipe-agent — AI 原生分析流水线:../geopipe-agent/SKILL.md
参考资源
- GitHub 仓库: https://github.com/geopandas/geopandas
- 官方文档: https://geopandas.readthedocs.io
- 官网: https://geopandas.org
- GeoParquet 规范: https://geoparquet.org/
- 中文教程(znlgis): https://znlgis.github.io/gis/tutorial/geopandas/


