如何优化OSMNX数据获取?批量检测全球十万点位道路归属
问题描述
现有一份包含约10万个带经纬度信息的全球多国点位CSV文件,需求是检测每个点位是否位于道路上。当前实现方式为针对每个点位调用OSMNX获取其周边100米范围的路网,转换为GeoDataFrame后判断相交关系,但处理海量点位时速度极慢。已知每个点位所属国家名称,求编程优化方案,比如批量获取大区域路网并缓存,避免重复调用API。
当前使用的代码:
def check_point(longitude,latitude): try: point_geom = Point(longitude,latitude) graph = ox.graph_from_point((latitude,longitude), dist=100) gdf_roads = ox.graph_to_gdfs(graph, nodes=False, edges=True) buffered_point = point_geom.buffer(0.00008) intersects = gdf_roads.intersects(buffered_point) return intersects.any() except Exception as e: print(e) return False
优化方案
1. 按国家批量获取路网并本地缓存
- 利用已知的国家名称,直接通过
ox.graph_from_place()获取整个国家(或按行政区拆分的子区域,比如州/省,避免单文件过大)的路网,替代单点小范围调用。 - 获取后将路网GeoDataFrame序列化保存到本地(比如用
gdf.to_pickle()存为Pickle文件,或gdf.to_file()存为GeoPackage格式),后续直接读取本地文件,彻底避免重复调用OSM API。 - 若国家面积过大,可按点位的经纬度分块、或行政区划拆分,获取对应子区域的路网,降低内存占用。
2. 批量点位空间匹配(替代单点循环)
- 将所有点位加载为一个GeoDataFrame,按国家分组处理。
- 对每个国家,加载对应的路网GeoDataFrame,用批量空间操作替代单点判断:
- 先给所有点位做统一缓冲区(保持原逻辑的0.00008缓冲距离),再用
gdf_roads.sjoin(gdf_points, predicate='intersects')直接得到所有位于道路附近的点位。 - 或通过批量遍历点位几何,结合空间索引快速判断相交关系,效率远高于单点循环。
- 先给所有点位做统一缓冲区(保持原逻辑的0.00008缓冲距离),再用
3. 空间索引加速匹配计算
- 对路网GeoDataFrame创建空间索引:
sindex = gdf_roads.sindex,判断点位与路网相交时,先通过索引快速筛选出可能相交的路网片段,再做精确判断,大幅减少无效计算量。
示例代码片段:
def batch_check_points(gdf_points, gdf_roads): sindex = gdf_roads.sindex results = [] for geom in gdf_points.geometry: buffered = geom.buffer(0.00008) # 空间索引筛选候选路网片段 candidate_idx = list(sindex.intersection(buffered.bounds)) if not candidate_idx: results.append(False) continue # 仅对候选片段做精确相交判断 intersects = gdf_roads.iloc[candidate_idx].intersects(buffered).any() results.append(intersects) gdf_points['on_road'] = results return gdf_points
4. 自定义路网过滤提前执行
- 如果需要筛选特定类型路网(比如仅保留主干道),在获取国家路网时就应用过滤器,而非每个点位处理时再筛选,减少后续数据量。示例:
# 按路网类型过滤 gdf_roads = ox.graph_to_gdfs( ox.graph_from_place("China", network_type='drive'), # 可选drive/walk/bike等 nodes=False, edges=True ) # 或自定义tag过滤 custom_filter = '["highway"~"motorway|primary|secondary"]' graph = ox.graph_from_place("China", custom_filter=custom_filter)
5. 并行处理(可选)
- 对按国家/区域分组后的点位,用多进程/多线程并行处理,充分利用CPU资源。比如使用
joblib的Parallel和delayed函数,或concurrent.futures模块实现并行批量判断。
内容的提问来源于stack exchange,提问作者Relicious
相关产品推荐
相关产品推荐

