You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为OSMnx道路网络绘图中的Edges设置自定义z-order层级?

OSMnx道路网络图z-order层级自定义解决方案

问题背景

我用OSMnx绘制带颜色数据的道路网络图,示例通过颜色展示介数中心性,但遇到问题:z-order层级设置导致浅色边在节点密集的路口被其他边覆盖。

OSMnx的plot_graph方法会调用GeoPandas的gdf.plot,后者基于Pandas的PlotAccessor实现。查阅OSMnx文档后未找到传递z-order参数的方式,想请教能否通过GeoPandas、Pandas或Matplotlib直接绘图,为道路网络的Edges指定自定义z-order层级?

原代码示例:

import networkx as nx
import osmnx as ox

place = 'Hornsea'
G = ox.graph_from_place(place, network_type="drive")

# Digraph removes parallel edges
# Line graph swaps nodes and edges
line_graph = nx.line_graph(ox.get_digraph(G))

betweenness_centrality = nx.betweenness_centrality(line_graph, weight='travel_time')

for edge in G.edges:
    if edge not in betweenness_centrality:
        nx.set_edge_attributes(G, {edge: 0}, 'betweenness_centrality')

betweenness_centrality = {(k[0], k[1], 0): v for k, v in betweenness_centrality.items()}
nx.set_edge_attributes(G, betweenness_centrality, "betweenness_centrality")

ec = ox.plot.get_edge_colors_by_attr(G, 'betweenness_centrality', cmap='plasma')  # "RdYlGn_r"
ew = [G.get_edge_data(*edge).get('betweenness_centrality', 0) * 10 + 0.25 for edge in G.edges]
fig, ax = ox.plot_graph(G, edge_color=ec, edge_linewidth=ew, node_size=0)
fig.savefig(f"images/{place}_betweenness_centrality.png", facecolor="w", dpi=1000, bbox_inches="tight")

原效果示例:
Hornsea介数中心性道路网络图

解决方案

完全可以绕过OSMnx的plot_graph,直接用GeoPandas+Matplotlib手动绘图,实现自定义边的z-order层级。核心逻辑是将图的边转换为GeoDataFrame,为每条边设置z-order值(让优先级高的边绘制在顶层),再分层渲染。

实现步骤

  1. 将OSMnx图转换为边的GeoDataFrame,提取所有边数据
  2. 为边添加zorder列,按介数中心性降序分配层级(值越大,绘制层级越高)
  3. 用Matplotlib创建画布,调用GeoDataFrame的plot方法,指定zorder参数

修改后的完整代码:

import networkx as nx
import osmnx as ox
import matplotlib.pyplot as plt

place = 'Hornsea'
G = ox.graph_from_place(place, network_type="drive")

# 保留原介数中心性计算逻辑
line_graph = nx.line_graph(ox.get_digraph(G))
betweenness_centrality = nx.betweenness_centrality(line_graph, weight='travel_time')

for edge in G.edges:
    if edge not in betweenness_centrality:
        nx.set_edge_attributes(G, {edge: 0}, 'betweenness_centrality')

betweenness_centrality = {(k[0], k[1], 0): v for k, v in betweenness_centrality.items()}
nx.set_edge_attributes(G, betweenness_centrality, "betweenness_centrality")

# 转换为边的GeoDataFrame
gdf_edges = ox.utils_graph.graph_to_gdfs(G, nodes=False, edges=True)
# 按介数中心性降序设置z-order:值越高的边,zorder越大,绘制在最上层
gdf_edges['zorder'] = gdf_edges['betweenness_centrality'].rank(ascending=False)

# 生成颜色和线宽数据
gdf_edges['edge_color'] = ox.plot.get_edge_colors_by_attr(G, 'betweenness_centrality', cmap='plasma')
gdf_edges['edge_width'] = gdf_edges['betweenness_centrality'] * 10 + 0.25

# 手动绘图控制层级
fig, ax = plt.subplots(figsize=(10, 10))
# 绘制边时指定zorder参数
gdf_edges.plot(
    ax=ax,
    color=gdf_edges['edge_color'],
    linewidth=gdf_edges['edge_width'],
    zorder=gdf_edges['zorder']
)
# 隐藏坐标轴
ax.set_axis_off()
# 保存图片
fig.savefig(f"images/{place}_betweenness_centrality.png", facecolor="w", dpi=1000, bbox_inches="tight")
plt.close()

关键说明

  • 直接使用GeoDataFrame绘图时,zorder参数可直接传入plot方法,完全控制图层顺序
  • 示例中用rank(ascending=False)让介数中心性最高的边获得最大z-order,确保重要的深色/宽边不会被浅色边覆盖
  • 若需按其他规则设置层级(如道路等级),只需修改zorder列的计算逻辑即可,比如用gdf_edges['highway'].map({'motorway':5, 'primary':4, 'secondary':3})来定义层级

内容的提问来源于stack exchange,提问作者George Willcox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:15:55