如何使用OSMnx对比2020与2021年柏林路网的节点和边差异
两期柏林骑行路网变更对比实操流程
变更识别核心逻辑
基于OSM实体的唯一稳定标识(osmid)做跨时间匹配,相比纯坐标匹配精度更高,可避免路网编辑中的微小位置偏移导致的误判。OSM分配的实体ID跨版本稳定,除非实体被完全删除后重新创建,否则不会发生变化。
第一步:识别节点变更
提取两期路网的节点osmid集合,通过集合差值计算得到新增、删除的节点集合:
# 提取节点osmid集合 nodes_20 = set(n[1]["osmid"] for n in G_20.nodes(data=True)) nodes_21 = set(n[1]["osmid"] for n in G_21.nodes(data=True)) # 集合差值计算变更 deleted_nodes = nodes_20 - nodes_21 # 2020年存在、2021年已删除的节点 added_nodes = nodes_21 - nodes_20 # 2021年相对新增的节点
第二步:识别边变更
路网的边为有向结构,采用(起点osmid, 终点osmid, 边osmid)三元组作为唯一匹配标识,同样通过集合差值计算变更:
# 提取边的唯一标识三元组 edges_20 = set((u, v, data["osmid"]) for u, v, data in G_20.edges(data=True)) edges_21 = set((u, v, data["osmid"]) for u, v, data in G_21.edges(data=True)) # 集合差值计算变更 deleted_edges = edges_20 - edges_21 # 2020年存在、2021年已删除的边 added_edges = edges_21 - edges_20 # 2021年相对新增的边
第三步:变更可视化
构建合并后的通用绘图对象,为不同类型的元素分配固定颜色,叠加图例完成展示:
# 构建统一的可视化图对象 G_viz = G_20.copy() G_viz.add_nodes_from(G_21.nodes(data=True)) G_viz.add_edges_from(G_21.edges(data=True)) # 节点颜色赋值 node_colors = [] for n, data in G_viz.nodes(data=True): osmid = data["osmid"] if osmid in added_nodes: node_colors.append("#2ecc71") # 新增节点:亮绿色 elif osmid in deleted_nodes: node_colors.append("#e74c3c") # 删除节点:亮红色 else: node_colors.append("#bdc3c7") # 共有节点:浅灰色 # 边颜色赋值 edge_colors = [] for u, v, data in G_viz.edges(data=True): edge_id = data["osmid"] if (u, v, edge_id) in added_edges: edge_colors.append("#2ecc71") # 新增边:亮绿色 elif (u, v, edge_id) in deleted_edges: edge_colors.append("#e74c3c") # 删除边:亮红色 else: edge_colors.append("#d6dbdf") # 共有边:浅灰色 # 绘制基础路网图 fig, ax = ox.plot_graph( G_viz, node_size=8, edge_linewidth=1.2, node_color=node_colors, edge_color=edge_colors, show=False, close=False, bgcolor="white" ) # 添加图例 from matplotlib.lines import Line2D legend_items = [ Line2D([0], [0], marker='o', color='w', markerfacecolor='#2ecc71', markersize=10, label='2021年新增路网元素'), Line2D([0], [0], marker='o', color='w', markerfacecolor='#e74c3c', markersize=10, label='2020年存在已删除路网元素'), Line2D([0], [0], marker='o', color='w', markerfacecolor='#bdc3c7', markersize=10, label='两期共有路网元素') ] ax.legend(handles=legend_items, loc='upper right', framealpha=1) plt.show()
实操注意事项
- 拉取两期路网时必须保持所有参数完全一致,包括过滤规则、简化开关、边界裁剪设置,避免因参数差异产生无意义的变更识别结果
- 若遇到OSM实体被编辑删除后重新录入(会生成新的osmid),可补充坐标校验逻辑:将经纬度差小于1米的节点判定为同一实体,避免把位置微调的原有元素误判为“新增+删除”的双向变更
- OSMnx会自动将双向道路拆分为两条有向边,匹配时无需额外做去重处理,边的osmid会关联原始OSM的way标识,不会出现漏判
内容的提问来源于stack exchange,提问作者Peter Fu2
相关产品推荐
相关产品推荐

