Pandas中使用shapely实现点与多边形匹配的最高效方案
点要素匹配多边形所属区域的高效实现方案
原实现采用双层iterrows遍历,时间复杂度为O(n*m)(n为点数、m为多边形数),且iterrows本身是pandas效率极低的遍历方式,超大数据量下耗时会指数级上升。以下是两种高效实现方案:
方案1:使用GeoPandas空间连接(推荐,生产环境最优)
GeoPandas是pandas的空间扩展,内置R树空间索引,空间连接sjoin会先通过索引过滤不可能包含目标点的多边形,仅对候选多边形做包含判断,性能是双层循环的数百到数千倍。
import geopandas as gpd # 将普通DataFrame转为GeoDataFrame,指定几何列和坐标参考系(按实际坐标系填写即可,示例值不影响逻辑运行) gdf1 = gpd.GeoDataFrame(df1, geometry='Point', crs="EPSG:4326") gdf2 = gpd.GeoDataFrame(df2, geometry='Polygon', crs="EPSG:4326") # 空间连接:匹配点所在的多边形,left连接模式保留所有点的原始记录 df_merged = gpd.sjoin(gdf1, gdf2, how='left', predicate='within') # 提取匹配到的Area-ID赋值到原df1 df1['Area-ID'] = df_merged['Area-ID']
方案2:使用Shapely STRtree索引(无额外依赖)
如果不想引入GeoPandas依赖,可以直接用Shapely自带的STRtree空间索引实现过滤,同样能大幅降低计算量:
from shapely.strtree import STRtree # 预存多边形列表和对应的Area-ID,构建空间索引 polygons = df2['Polygon'].tolist() area_ids = df2['Area-ID'].tolist() tree = STRtree(polygons) def get_matched_area(point): # 先通过索引快速筛选可能包含当前点的候选多边形下标 candidate_indexes = tree.query(point) for idx in candidate_indexes: if polygons[idx].contains(point): return area_ids[idx] return None # 无匹配区域返回空值 # 批量应用匹配逻辑到所有点 df1['Area-ID'] = df1['Point'].apply(get_matched_area)
性能说明
- 10万点+1万多边形的场景下,上述两种方案耗时都可以控制在10秒内,远低于原双层循环的数小时耗时
- 两种方案均避免了全量遍历多边形,时间复杂度降低至O(n*logm)
内容的提问来源于stack exchange,提问作者TvCasteren
相关产品推荐
相关产品推荐

