OSMnx调用plot_graph_route()报KeyError:'length'如何解决
问题:OSMnx调用plot_graph_route抛出KeyError: 'length'
开发快递配送最优路径算法时,使用OSMnx的plot_graph_route()函数触发KeyError: 'length'报错,报错堆栈如下:
"C:\Python38\lib\site-packages\osmnx\plot.py", line 303, in plot_graph_route data = min(G.get_edge_data(u, v).values(), key=lambda d: d["length"]) File "C:\Python38\lib\site-packages\osmnx\plot.py", line 303, in <lambda> data = min(G.get_edge_data(u, v).values(), key=lambda d: d["length"]) KeyError: 'length'
排查后初步定位报错和节点对[1916534315,1916534308]相关,两节点已连通,手动添加双向边后仍报错,节点间路径通过NetworkX的shortest_path_length()计算得到,复现代码如下:
import networkx as nx import osmnx as ox import requests import numpy as np a= [1916534315,1916534308] #list_of_problem_node G = ox.graph_from_place('Gumi, Gyeongsangbuk-do, Korea', network_type='drive')#graph of I want to find ########## for save and load convinience # ox.save_graphml(G,'gumimap') # G = ox.load_graphml('gumimap') G.add_edge(1916534315,1916534308) G.add_edge(1916534308,1916534315) G=ox.utils_graph.get_largest_component(G,strongly=True) path=nx.shortest_path_length(G,a[0],a[1]) fig1_1, ax = ox.plot_graph_route(G, path, route_linewidth=6, node_size=0.5)
问题原因
代码里存在两个核心错误,直接触发该报错:
- 函数用错:
nx.shortest_path_length()返回的是两点间最短路径的长度数值(浮点数/整数),不是路径经过的节点序列。plot_graph_route()要求第二个传入参数是按顺序排列的路径节点列表,传入数值后函数会把数值当成节点ID遍历取边,完全匹配不到正确的边数据。 - 手动添加的边缺少必填属性:OSMnx内置的所有路由、绘图逻辑,都默认路网每条边带有
length属性(边的实际长度,单位米)。用G.add_edge()加双向边时没有传入length参数,这两条手动添加的边属性为空,后续遍历边取length字段时直接触发键错误。
修复方案
按以下步骤修改代码即可解决:
- 把计算路径的函数从
nx.shortest_path_length()换成nx.shortest_path(),该函数才会返回按节点顺序排列的路径列表 - 手动加边时补充
length属性,值可按实际业务设置,也可通过节点坐标计算球面直线距离,符合OSMnx的属性规范 - 操作路网后统一调用OSMnx自带的
ox.add_edge_lengths()函数,给全图所有缺失长度属性的边自动补算长度,避免漏加属性
修复后的可运行代码:
import networkx as nx import osmnx as ox import numpy as np a = [1916534315, 1916534308] G = ox.graph_from_place('Gumi, Gyeongsangbuk-do, Korea', network_type='drive') # 自动补全全图所有边的length属性,避免字段缺失 G = ox.add_edge_lengths(G) # 手动加边必须传入length属性,示例设置为10米,可按实际道路情况调整 G.add_edge(1916534315, 1916534308, length=10) G.add_edge(1916534308, 1916534315, length=10) G = ox.utils_graph.get_largest_component(G, strongly=True) # 注意用shortest_path获取节点路径列表,指定length为权重计算最短距离路径 path = nx.shortest_path(G, a[0], a[1], weight='length') fig1_1, ax = ox.plot_graph_route(G, path, route_linewidth=6, node_size=0.5)
额外提示:后续做配送路径规划时,建议直接用OSMnx封装好的
ox.shortest_path()函数,会自动适配路网权重属性,减少手动调用NetworkX函数出现的参数不匹配问题。
内容的提问来源于stack exchange,提问作者haonol
相关产品推荐
相关产品推荐

