基于OSMnx与Python筛选东京涩谷不同距离道路节点求助
问题排查:OSMnx筛选涩谷4度道路节点异常
我用Python的OSMnx工具获取东京涩谷的驾车道路网络,需求是筛选出两类4度道路节点:
- 与相邻节点的最短路径距离小于30米的节点
- 与相邻节点的最短路径距离大于100米的节点
但编写的代码无法得到预期结果,以下是原代码:
import osmnx as ox import geopandas as gpd import pandas as pd import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import math import networkx as nx from colorspacious import cspace_converter ward_names = [ "Shibuya", ] graph = ox.graph_from_place(ward_names, network_type="drive") nodes = ox.graph_to_gdfs(graph, nodes=True, edges=False) edges = ox.graph_to_gdfs(graph, nodes=False, edges=True) print("Number of nodes:", len(nodes)) print("Number of edges:", len(edges)) ox.plot_graph(graph) gdf_nodes, gdf_edges = ox.graph_to_gdfs(graph) # Find nodes that are separated by a distance of less than 30 meters and lead to 4 edges # s_cross = Small crossing s_cross = [] for node in graph.nodes(): if len(list(graph.neighbors(node))) == 4: # distance distances = nx.shortest_path_length(graph, node) if max(distances.values()) <= 30: s_cross.append(node) s_cross # Find nodes that are separated by a distance of more than 100 meters and lead to 4 edges # b_cross = Big crossing b_cross = [] for node in graph.nodes(): if len(list(graph.neighbors(node))) == 4: # distance distances = nx.shortest_path_length(graph, node) if max(distances.values()) >= 100: b_cross.append(node) b_cross
问题根源分析
- 最短路径长度计算逻辑错误:
nx.shortest_path_length默认返回路径经过的节点数量,而非实际道路距离。必须指定weight='length'参数,调用OSMnx边属性中存储的实际道路长度(单位:米)。 - 不必要的全局计算:原代码计算当前节点到所有节点的最短路径,而需求只关注相邻节点的距离,完全不需要遍历整个图。
- 判断条件偏差:原代码取所有节点到目标节点的最大距离,这和“相邻节点距离”的需求完全不符,应该只检查当前节点与直接邻居的边长度。
修正后的代码
import osmnx as ox import networkx as nx ward_names = ["Shibuya"] graph = ox.graph_from_place(ward_names, network_type="drive") # 筛选4度节点并分类 s_cross = [] # 所有相邻节点距离<30米的4度节点 b_cross = [] # 存在相邻节点距离>100米的4度节点 for node in graph.nodes(): neighbors = list(graph.neighbors(node)) if len(neighbors) != 4: continue # 获取当前节点与每个邻居的边长度(取最短边) neighbor_distances = [] for neighbor in neighbors: edge_data = graph.get_edge_data(node, neighbor) lengths = [d['length'] for d in edge_data.values()] neighbor_distances.append(min(lengths)) # 根据需求分类 if all(d <= 30 for d in neighbor_distances): s_cross.append(node) if any(d >= 100 for d in neighbor_distances): b_cross.append(node) print(f"短距离4度节点数量:{len(s_cross)}") print(f"长距离4度节点数量:{len(b_cross)}") # 可视化验证结果 nx.set_node_attributes(graph, False, 'is_s_cross') nx.set_node_attributes(graph, False, 'is_b_cross') for node in s_cross: graph.nodes[node]['is_s_cross'] = True for node in b_cross: graph.nodes[node]['is_b_cross'] = True node_color = [] for node in graph.nodes(): if graph.nodes[node]['is_s_cross']: node_color.append('red') elif graph.nodes[node]['is_b_cross']: node_color.append('blue') else: node_color.append('gray') ox.plot_graph(graph, node_color=node_color, node_size=30)
修正说明
- 直接读取节点与邻居的边属性
length,避免冗余的全局最短路径计算,提升效率。 - 按需调整判断逻辑:
- 若需求为“存在相邻节点距离小于30米”,可将
all改为any - 若需求为“所有相邻节点距离大于100米”,可将
any改为all
- 若需求为“存在相邻节点距离小于30米”,可将
- 增加可视化代码,直观验证筛选结果的正确性。
内容的提问来源于stack exchange,提问作者Naohiro Miyaguchi
相关产品推荐
相关产品推荐

