如何加速两个pandas DataFrame间带坐标边界条件的迭代匹配操作
性能瓶颈原因
你现有代码的时间复杂度为O(M*N)(M为A的30万行,N为B的1万行),iterrows遍历本身效率极低,加上每行都要全量遍历B做条件判断,运算量达到30亿次,自然运行速度极慢。
推荐优化方案
方案1:使用geopandas空间连接(效率最高,首选)
基于R树空间索引实现,避免全量遍历匹配,30万行数据可在数秒内完成处理,且天然适配空间匹配场景。
代码示例:
import geopandas as gpd from shapely.geometry import Point, box # 将A转换为点要素GeoDataFrame gdf_A = gpd.GeoDataFrame( A, geometry=gpd.points_from_xy(A.longitude, A.latitude), crs="EPSG:4326" ) # 调整B的边界适配左闭右开的匹配规则,避免边界点匹配错误 B_adj = B.copy() epsilon = 1e-9 B_adj['max_latitude'] -= epsilon B_adj['max_longitude'] -= epsilon # 将B转换为边界框要素GeoDataFrame gdf_B = gpd.GeoDataFrame( B_adj[['ID']], geometry = B_adj.apply(lambda row: box(row.min_longitude, row.min_latitude, row.max_longitude, row.max_latitude), axis=1), crs="EPSG:4326" ) # 空间连接匹配,直接得到带ID的结果 gdf_merged = gpd.sjoin(gdf_A, gdf_B, how='left', predicate='within') A['ID'] = gdf_merged['ID']
方案2:纯numpy向量化实现(无额外依赖)
如果不想安装geopandas相关依赖,用numpy广播特性一次性完成全量条件判断,效率比循环高两个数量级以上,30万行处理耗时在10秒内。
代码示例:
import numpy as np # 提取所有字段为numpy数组 lat_A = A['latitude'].values[:, np.newaxis] lon_A = A['longitude'].values[:, np.newaxis] min_lat_B = B['min_latitude'].values max_lat_B = B['max_latitude'].values min_lon_B = B['min_longitude'].values max_lon_B = B['max_longitude'].values id_arr = B['ID'].values # 一次性生成所有匹配的布尔矩阵 match_mask = (lat_A >= min_lat_B) & (lat_A < max_lat_B) & (lon_A >= min_lon_B) & (lon_A < max_lon_B) # 取每行第一个匹配的ID(你已保证匹配唯一,无需处理多匹配问题) match_idx = match_mask.argmax(axis=1) has_match = match_mask.any(axis=1) A['ID'] = np.where(has_match, id_arr[match_idx], None)
验证结果
以上两种方案运行你提供的示例数据,最终得到的ID列就是预期的['9ae8704', '0uh0478', '3ef4522', '0uh0478'],完全符合需求。
内容的提问来源于stack exchange,提问作者ruby
相关产品推荐
相关产品推荐

