GeoPandas 空间连接 sjoin 结果为空怎么办?CRS、几何、索引三步排查
Dr.GIS
GIS研习社 · 工具流程与项目排障

在使用 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。