You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OSMnx保存再加载后节点与边数量不匹配问题咨询

OSMnx导出再加载后节点与边数量不一致

问题重现

使用OSMnx下载旧金山道路网络时,两种方式得到的节点、边数量不一致:

  • 直接将图转为GeoDataFrame:9671个节点、16030条边
  • 先导出为XML再重新加载,再转GeoDataFrame:9649个节点、15975条边

相关代码:

import osmnx as ox

utn = ox.settings.useful_tags_node
oxna = ox.settings.osm_xml_node_attrs
oxnt = ox.settings.osm_xml_node_tags
utw = ox.settings.useful_tags_way
oxwa = ox.settings.osm_xml_way_attrs
oxwt = ox.settings.osm_xml_way_tags
utn = list(set(utn + oxna + oxnt))
utw = list(set(utw + oxwa + oxwt))
ox.settings.all_oneway = True
ox.settings.useful_tags_node = utn
ox.settings.useful_tags_way = utw
G = ox.graph_from_bbox(37.708300, 37.813300, -122.517100, -122.355100, network_type='drive')

nodes, edges = ox.utils_graph.graph_to_gdfs(G)
print(nodes.shape)
print(edges.shape)

ox.io.save_graph_xml(G, filepath="./data/SF_Road_Network.osm")

Recreated_G = ox.graph_from_xml('./data/SF_Road_Network.osm')
recreated_nodes, recreated_edges = ox.utils_graph.graph_to_gdfs(Recreated_G)
print(recreated_nodes.shape)
print(recreated_edges.shape)

原因分析

  1. 合成节点丢失:OSMnx构建图时会自动生成一些合成节点(比如分割长路段、处理转向限制时添加的节点),这些节点不属于原始OSM数据,save_graph_xml()只会保存原始OSM元素,不会保存这些合成节点,导致加载后节点数量减少。
  2. 加载时的过滤差异:graph_from_xml()加载时会默认根据network_type过滤道路元素,即便你导出的图已经过滤过,但加载时的标签处理逻辑和原图构建时可能存在差异,导致部分边被二次过滤。
  3. 单向边设置未同步:你设置了ox.settings.all_oneway = True,但加载XML时如果没有提前同步这个设置,加载后的图在处理单向边时会和原图逻辑不一致,导致边数量变化。

解决办法

方法1:使用GraphML格式保存加载(推荐)

GraphML格式会完整保存OSMnx生成的所有节点、边以及图的属性,包括合成节点,能完全还原原图:

import osmnx as ox

# 保持原有的settings配置不变
utn = ox.settings.useful_tags_node
oxna = ox.settings.osm_xml_node_attrs
oxnt = ox.settings.osm_xml_node_tags
utw = ox.settings.useful_tags_way
oxwa = ox.settings.osm_xml_way_attrs
oxwt = ox.settings.osm_xml_way_tags
utn = list(set(utn + oxna + oxnt))
utw = list(set(utw + oxwa + oxwt))
ox.settings.all_oneway = True
ox.settings.useful_tags_node = utn
ox.settings.useful_tags_way = utw

# 构建原图
G = ox.graph_from_bbox(37.708300, 37.813300, -122.517100, -122.355100, network_type='drive')
nodes, edges = ox.utils_graph.graph_to_gdfs(G)
print("原图节点数:", nodes.shape[0])
print("原图边数:", edges.shape[0])

# 用GraphML保存并加载
ox.save_graphml(G, filepath="./data/SF_Road_Network.graphml")
Recreated_G = ox.load_graphml('./data/SF_Road_Network.graphml')
recreated_nodes, recreated_edges = ox.utils_graph.graph_to_gdfs(Recreated_G)
print("加载后节点数:", recreated_nodes.shape[0])
print("加载后边数:", recreated_edges.shape[0])

方法2:同步加载时的设置

如果必须使用XML格式,加载前要确保所有settings和原图构建时完全一致,包括network_type参数:

# 加载XML前先同步设置
ox.settings.all_oneway = True
ox.settings.useful_tags_node = utn
ox.settings.useful_tags_way = utw
Recreated_G = ox.graph_from_xml('./data/SF_Road_Network.osm', network_type='drive')

方法3:验证丢失元素

可以对比两个图的节点ID,找出丢失的节点,查看其属性确认是否为合成节点:

# 找出丢失的节点
original_node_ids = set(nodes.index)
recreated_node_ids = set(recreated_nodes.index)
missing_nodes = original_node_ids - recreated_node_ids
print("丢失的节点ID:", missing_nodes)

# 查看其中一个丢失节点的属性
print(G.nodes[next(iter(missing_nodes))])

内容的提问来源于stack exchange,提问作者Kuldip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:53:13