如何优化Pandas点坐标匹配区域标签的计算效率
优化方案
你当前的实现慢是因为在Python层循环遍历DF2的每一行,每次都要全量扫描DF1做条件判断,属于纯IO绑定的低效操作,下面提供两种适用于不同场景的高效实现:
方案1:Numpy广播向量化匹配(适合DF2行数<1000的场景)
完全消除Python层面的循环,用numpy的广播特性一次性完成所有点位和所有区域的匹配判断,性能比循环实现高1~2个数量级:
import numpy as np # 提取DF2的边界和标签转为numpy数组 minlat = DF2['minlat'].values maxlat = DF2['maxlat'].values minlon = DF2['minlong'].values maxlon = DF2['maxlong'].values labels = DF2['STRING'].values # 给DF1经纬度增加维度适配广播 points_lat = DF1['latitude'].values[:, np.newaxis] points_lon = DF1['longitude'].values[:, np.newaxis] # 生成匹配掩码矩阵:行对应DF1点位,列对应DF2区域,值为True表示点位落在对应区域 match_mask = (points_lat >= minlat) & (points_lat < maxlat) & (points_lon >= minlon) & (points_lon < maxlon) # 取每个点位第一个匹配的区域,无匹配则赋值为None match_idx = match_mask.argmax(axis=1) match_idx[~match_mask.any(axis=1)] = -1 DF1['LABEL'] = np.where(match_idx == -1, None, labels[match_idx])
方案2:Geopandas空间索引匹配(适合大数据量场景)
如果DF2的区域数超过1000,或者DF1的点位规模达到十万级以上,推荐用专业的空间匹配方案,底层基于R树索引,时间复杂度仅为O(M log N),性能远高于暴力匹配:
import geopandas as gpd from shapely.geometry import Point, box # DF1转为点GeoDataFrame gdf_points = gpd.GeoDataFrame( DF1, geometry=gpd.points_from_xy(DF1.longitude, DF1.latitude), crs="EPSG:4326" ) # DF2转为矩形区域GeoDataFrame gdf_areas = gpd.GeoDataFrame( DF2, geometry=DF2.apply(lambda x: box(x.minlong, x.minlat, x.maxlong, x.maxlat), axis=1), crs="EPSG:4326" ) # 左连接匹配点位和区域 join_result = gpd.sjoin(gdf_points, gdf_areas[['geometry', 'STRING']], how='left', predicate='within') DF1['LABEL'] = join_result['STRING']
注意事项
你之前贴的方案2、3代码里存在笔误:minLong=DF2.loc[i:i,'maxLat'].at[i] 错误取了maxLat列作为minLong值,实际使用前需要先修正这个逻辑错误。
内容的提问来源于stack exchange,提问作者Giuditta Davini
相关产品推荐
相关产品推荐

