GeoPandas 空间连接 sjoin 结果为空怎么办?CRS、几何、索引三步排查

在使用 GeoPandas 做空间分析时,sjoin 是一个非常常用的函数。比如判断点落在哪个行政区内、将 POI 点位匹配到街道、给采样点批量挂接区县字段等,都离不开空间连接。
但很多初学者会遇到一个典型问题:两个图层在地图上看起来明明有重叠,为什么 geopandas.sjoin() 之后结果为空?
一、先确认:sjoin 结果为空是什么意思
GeoPandas.sjoin() 的作用是根据空间关系连接两个 GeoDataFrame。常见写法如下:
result = gpd.sjoin(points, polygons, how="inner", predicate="within")
如果结果为空,通常表示 GeoPandas 没有找到任何符合空间关系的要素对。常见原因包括:
- 两个图层 CRS 不一致。
- CRS 信息缺失或被错误设置。
- 几何对象为空或无效。
predicate参数用错。- 左右表顺序和空间关系不匹配。
- 数据边界只是看起来接近,但实际没有相交。
二、第一步:检查 CRS 坐标系是否一致
sjoin 结果为空,最常见的原因就是 CRS 不一致。先打印两个图层的 CRS:
print(points.crs)
print(polygons.crs)
如果一个是 EPSG:4326,另一个是 EPSG:3857,就说明两个图层不在同一个坐标系下,需要先统一:
polygons = polygons.to_crs(points.crs)
三、常见 CRS 对比表
| CRS | 常见名称 | 坐标单位 | 常见用途 |
|---|---|---|---|
| EPSG:4326 | WGS84 经纬度 | 度 | GPS、GeoJSON、互联网数据 |
| EPSG:3857 | Web Mercator | 米 | Web 地图底图、瓦片地图 |
| EPSG:4490 | CGCS2000 经纬度 | 度 | 国内测绘数据常见 |
| 投影坐标系 | UTM、高斯克吕格等 | 米 | 距离、面积、缓冲区分析 |
四、注意 set_crs 和 to_crs 的区别
很多人会把 set_crs() 和 to_crs() 混用,这是非常容易导致空间连接为空的坑。
| 方法 | 作用 | 是否改变坐标值 | 使用场景 |
|---|---|---|---|
set_crs() | 给数据指定 CRS 标签 | 否 | 数据本来有坐标系,但文件里缺失 CRS 信息 |
to_crs() | 坐标转换 | 是 | 数据已有 CRS,需要转换到另一个 CRS |
五、第二步:检查几何是否为空或无效
CRS 没问题之后,下一步要检查 geometry 字段:
print(points.geometry.is_empty.sum())
print(polygons.geometry.is_empty.sum())
print(points.geometry.isna().sum())
print(polygons.geometry.isna().sum())
如果存在空几何,建议先过滤:
points = points[points.geometry.notna() & ~points.geometry.is_empty]
polygons = polygons[polygons.geometry.notna() & ~polygons.geometry.is_empty]
面数据还要检查是否合法:
print(polygons.is_valid.value_counts())
polygons["geometry"] = polygons.geometry.make_valid()
六、第三步:检查 predicate 参数是否用错
predicate 决定空间关系判断方式。点落在面内通常写:
gpd.sjoin(points, polygons, how="inner", predicate="within")
如果左右表顺序反了,就变成了“面是否在点内部”,通常匹配不到。
| predicate | 含义 | 常见场景 |
|---|---|---|
within | 左侧几何在右侧几何内部 | 点匹配行政区 |
contains | 左侧几何包含右侧几何 | 面查找内部点 |
intersects | 两个几何相交即可 | 面面叠加、线面相交 |
touches | 边界接触 | 邻接关系分析 |
七、推荐的完整排查顺序
- 打印两个图层的
crs。 - 打印两个图层的
total_bounds。 - 统一 CRS,优先使用
to_crs()。 - 删除空 geometry。
- 修复无效 geometry。
- 先用
intersects测试是否有结果。 - 再根据业务需求改成
within、contains或其他 predicate。 - 检查左右表顺序是否写反。
八、总结
GeoPandas 的 sjoin 结果为空,通常不是函数本身的问题,而是数据或参数没有满足空间连接条件。最实用的排查流程是:看 CRS、看 total_bounds、清理 geometry、用 intersects 测试,再换成业务真正需要的 predicate。
相关文章
-
gis python 开发入门全解析,gis Python新手指南 2025-09-06 12:13:26
-
gis python开发者必看,gis Python基础入门全解析 2025-09-06 12:13:25
-
gis Python入门指南,从解析gis python基础知识谈起 2025-09-06 12:13:24
-
gis Python入门指南,从解析Gis python库开始 2025-09-06 12:13:23
-
GISer的Python学习路径:从基础语法到GeoPandas空间数据分析 2025-08-23 12:53:35
-
GeoPandas实战:用几行代码完成空间数据读写、坐标转换与可视化 2025-08-19 11:03:19
-
Jupyter Notebook + GIS:打造可交互、可复现的空间分析报告 2025-07-12 20:36:08
热门标签
最新资讯
2026-04-13 08:30:01
2026-04-12 08:30:02
2026-04-12 08:30:02
2026-04-12 08:30:02
2026-04-12 08:30:02
2026-04-12 08:30:02
2026-04-12 08:30:02
2026-04-12 08:30:01
2026-04-12 08:30:01
2026-04-12 08:30:01