坐标距离计算的资源最优方案:大样本100米邻域计数
高效统计指定坐标100米范围内的观测数量方案
直接循环计算每个点与20万+住宅坐标的距离效率极低,推荐用空间索引/近邻搜索数据结构将时间复杂度从O(n*m)降至O(n log m),以下是两种最优方案:
方案一:Geopandas + 空间索引(地理场景首选)
适合带地理坐标系的坐标数据,直观且支持复杂空间操作:
- 将普通DataFrame转为GeoDataFrame,确保坐标系为米制单位(如UTM),若原始是经纬度需先转换,否则距离计算会出错
- 为20万+住宅数据构建空间索引,通过边界框快速过滤候选点,再精确计算距离
示例代码:
import geopandas as gpd from shapely.geometry import Point # 假设原始数据是WGS84经纬度,转换为目标区域对应的UTM米制坐标系(示例用中国东部EPSG:32650) df1 = gpd.GeoDataFrame(df1, geometry=gpd.points_from_xy(df1.X, df1.Y), crs="EPSG:4326") df1 = df1.to_crs("EPSG:32650") df2 = gpd.GeoDataFrame(df2, geometry=gpd.points_from_xy(df2.X, df2.Y), crs="EPSG:4326") df2 = df2.to_crs("EPSG:32650") # 构建df2的空间索引 sindex = df2.sindex # 定义统计函数:先过滤候选点再精确计算距离 def count_nearby(point): # 空间索引快速筛选边界框内的候选点 candidate_idx = list(sindex.intersection(point.buffer(100).bounds)) candidates = df2.iloc[candidate_idx] # 精确筛选100米内的点并计数 return len(candidates[candidates.distance(point) <= 100]) # 批量计算并赋值 df1['observations_within100m'] = df1.geometry.apply(count_nearby)
方案二:Scikit-learn BallTree(纯数值坐标最快)
如果是平面米制坐标(无需地理坐标系转换),用BallTree做近邻搜索速度最优:
import numpy as np from sklearn.neighbors import BallTree # 提取坐标数组 df2_coords = df2[['X', 'Y']].values # 构建BallTree,平面坐标用欧氏距离 tree = BallTree(df2_coords, metric='euclidean') # 批量查询每个点100米内的数量 counts, _ = tree.query_radius(df1[['X', 'Y']].values, r=100, count_only=True) df1['observations_within100m'] = counts
关键注意事项
- 坐标系必须统一为米制:若用经纬度直接计算欧氏距离会得到错误的米数,需转UTM或用
haversine球面距离(需将经纬度转弧度) - 性能差异:BallTree速度远快于Geopandas,适合纯数值坐标场景;Geopandas更灵活,支持复杂地理操作
- 内存占用:20万行数据的BallTree内存占用极低,400行查询可瞬间完成
内容的提问来源于stack exchange,提问作者TvCasteren
相关产品推荐
相关产品推荐

