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)
原因分析
- 合成节点丢失:OSMnx构建图时会自动生成一些合成节点(比如分割长路段、处理转向限制时添加的节点),这些节点不属于原始OSM数据,
save_graph_xml()只会保存原始OSM元素,不会保存这些合成节点,导致加载后节点数量减少。 - 加载时的过滤差异:
graph_from_xml()加载时会默认根据network_type过滤道路元素,即便你导出的图已经过滤过,但加载时的标签处理逻辑和原图构建时可能存在差异,导致部分边被二次过滤。 - 单向边设置未同步:你设置了
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
相关产品推荐
相关产品推荐

