OSMNX与NetworkX升级后代码报错求助:NetworkXError节点不在有向图
解决OSMNX与NetworkX版本升级后「节点不在有向图」的错误
嘿,这个问题我太熟了——你遇到的NetworkXError: The node osmid is not in the digraph,本质是拿合并后的新图节点去原始图里找邻居,这俩图的节点ID完全不搭边,原始图肯定找不到啊!
问题根源
ox.consolidate_intersections()这个函数会生成一个全新的路网图,它会把原始图里距离很近的交点合并成新节点,所以新图inter的节点ID和原始图G的节点ID是完全不同的两个体系。你遍历inter的节点,却去G里调用nx.neighbors(),自然会报错。
最直接的解决方案:用合并后的图操作
既然你已经生成了合并交点的图,直接用它来获取邻居和边数据就好,修改后的代码如下:
import osmnx as ox import networkx as nx # 获取原始路网图 G = ox.graph_from_place('Piedmont, CA, USA', network_type='drive') # 投影后合并交点,得到新图 inter = ox.consolidate_intersections(ox.project_graph(G)) # 获取新图的节点GeoDataFrame(注意节点ID在index里) nodes = ox.graph_to_gdfs(inter, edges=False) connections = {} # 遍历新图的节点ID(从index取) for n in nodes.index: connections[n] = set() # 在合并后的图inter里找邻居 for nbr in nx.neighbors(inter, n): # NetworkX有向图的边数据是嵌套字典,需要遍历边ID edge_entries = inter.get_edge_data(n, nbr) for edge_id in edge_entries: edge_name = edge_entries[edge_id].get('name') if edge_name: # 过滤空的道路名称 connections[n].add(str(edge_name))
如果必须用原始图G:获取节点映射关系
要是你确实需要基于原始图做操作,那得让consolidate_intersections()返回节点的映射字典,这样就能知道新节点对应哪些原始节点:
import osmnx as ox import networkx as nx G = ox.graph_from_place('Piedmont, CA, USA', network_type='drive') projected_G = ox.project_graph(G) # 开启return_dicts参数,获取新旧节点的映射关系 inter, node_mappings = ox.consolidate_intersections(projected_G, return_dicts=True) nodes = ox.graph_to_gdfs(inter, edges=False) connections = {} for new_node in nodes.index: connections[new_node] = set() # 找到这个新节点对应的所有原始节点 original_nodes = [old_n for old_n, new_n in node_mappings['old_to_new'].items() if new_n == new_node] # 遍历每个原始节点,在原始图G里找邻居 for old_node in original_nodes: for nbr in nx.neighbors(G, old_node): edge_entries = G.get_edge_data(old_node, nbr) for edge_id in edge_entries: edge_name = edge_entries[edge_id].get('name') if edge_name: connections[new_node].add(str(edge_name))
版本升级后的小提醒
OSMNX 1.0+和NetworkX 2.6+的API有不少变化:
ox.graph_to_gdfs()返回的节点GeoDataFrame,节点ID是存在index里的,不是单独的列,所以遍历的时候要用nodes.index- NetworkX的有向图中,
get_edge_data(u, v)返回的是{edge_id: 属性字典}的结构,必须遍历edge_id才能拿到每条边的属性
内容的提问来源于stack exchange,提问作者Kris
相关产品推荐
相关产品推荐

