查找同一GeoDataFrame内每个点指定半径范围内所有点的方法
GeoPandas指定半径范围邻点查询实现方案
直接通过缓冲区构造+空间连接的方式即可一次性拿到每个点半径范围内的所有邻点,不需要绕最近邻逻辑,具体实现步骤如下:
- 首先基于原始点图层生成指定半径的缓冲区图层,作为空间匹配的查询范围
- 通过空间左连接,把所有落在缓冲区内的点匹配到对应原始点,剔除匹配到自身的记录
- 将匹配到的邻点按所属原始点分组编号,透转为宽表结构后和原始GeoDataFrame合并,即可得到要求的列结构
完整实现代码
import geopandas as gpd from shapely.geometry import Point import pandas as pd # 原始示例数据 df = gpd.GeoDataFrame([[0, 'A', Point(10,12)], [1, 'B', Point(14,8)], [2, 'C', Point(100,2)], [3, 'D' ,Point(20,10)]], columns=['ID','Value','geometry'], crs="EPSG:3857") # 替换为你数据实际的投影坐标系,单位需和半径单位一致 search_radius = 10 # 自定义搜索半径 # 生成每个点的搜索缓冲区 buffer_gdf = df.copy() buffer_gdf['geometry'] = buffer_gdf.geometry.buffer(search_radius) # 空间连接匹配所有落在缓冲区内的邻点 join_result = gpd.sjoin( left_df=buffer_gdf, right_df=df[["Value", "geometry"]], how="left", predicate="contains", rsuffix="_neigh" ) # 剔除匹配到点自身的记录 join_result = join_result[join_result["ID"] != join_result["index_right"]].reset_index(drop=True) # 为每个点匹配到的邻点添加序号 join_result["neigh_seq"] = join_result.groupby("ID").cumcount() + 1 # 透转为宽表,生成要求的列结构 val_col = join_result.pivot( index="ID", columns="neigh_seq", values="Value_neigh" ).add_prefix("value_of_point_in_range_") geom_col = join_result.pivot( index="ID", columns="neigh_seq", values="geometry_neigh" ).add_prefix("geometry_of_point_in_range_") neigh_table = pd.concat([val_col, geom_col], axis=1).sort_index(axis=1) # 和原始数据合并得到最终结果 final_gdf = df.merge(neigh_table, on="ID", how="left")
结果说明
针对你提供的示例数据,运行后结果匹配逻辑为:
- ID为0的A点半径10范围内仅存在B点,会填充1组邻点字段
- ID为1的B点半径10范围内存在A、D两个点,会填充2组邻点字段
- ID为2的C点半径10范围内无其他点,邻点字段为空值
- ID为3的D点半径10范围内仅存在B点,会填充1组邻点字段
注意事项:如果你的原始数据是WGS84经纬度坐标系(EPSG:4326),不要直接用经纬度做缓冲区,需先转换为对应研究区的投影坐标系(单位为米/千米等长度单位)再计算半径,否则距离单位为度,查询结果会完全错误。
该方法是空间邻域查询的标准实现,相比逐点循环计算距离、固定数量最近邻筛选的方案,在数据量较大时运行效率有明显优势,且天然支持每个点邻点数量不固定的场景。
内容的提问来源于stack exchange,提问作者Obst
相关产品推荐
相关产品推荐

