能否使用Python库Bokeh将NetworkX网络图叠加至地理地图之上?
在Bokeh中叠加NetworkX网络图到地理地图
完全可以实现将NetworkX的节点交互图叠加到Bokeh地理地图上,核心思路是让网络图的节点坐标与地理地图的坐标系统对齐,再将两个图层添加到同一个Bokeh Figure中。以下是具体实现步骤和示例:
关键步骤
- 统一坐标系统:地理地图通常使用经纬度(WGS84),而Bokeh的
GraphRenderer需要对应的投影坐标(比如墨卡托投影),需先把NetworkX节点的经纬度转换为墨卡托坐标。 - 共享同一个Figure:不管是用Bokeh内置的
GMap(谷歌地图)还是GeoJSONDataSource加载自定义地理数据,都要把网络图的渲染器添加到同一个Figure对象中。
示例代码
1. 依赖导入
import networkx as nx from bokeh.plotting import figure, show, output_file from bokeh.models import GraphRenderer, StaticLayoutProvider, GMapOptions, GMapPlot, ColumnDataSource, CARTODBPOSITRON from bokeh.transform import linear_cmap from bokeh.palettes import Viridis256 from pyproj import Transformer # 初始化经纬度转墨卡托的转换器 transformer = Transformer.from_crs("EPSG:4326", "EPSG:3857", always_xy=True)
2. 准备NetworkX图与地理坐标
# 创建简单的NetworkX图 G = nx.Graph() G.add_nodes_from([1, 2, 3, 4]) G.add_edges_from([(1,2), (2,3), (3,4), (4,1)]) # 给每个节点绑定经纬度(示例坐标:国内几个城市) node_coords = { 1: (116.4074, 39.9042), # 北京 2: (121.4737, 31.2304), # 上海 3: (113.2644, 23.1291), # 广州 4: (104.0668, 30.5728) # 成都 } # 转换经纬度到墨卡托坐标 layout = {node: transformer.transform(lon, lat) for node, (lon, lat) in node_coords.items()}
3. 创建地理地图(以免费瓦片地图为例)
# 创建基础Figure,适配墨卡托坐标范围 plot = figure(x_range=(-13000000, 7000000), y_range=(-5000000, 6000000), x_axis_type="mercator", y_axis_type="mercator") # 添加免费地图瓦片 plot.add_tile(CARTODBPOSITRON)
4. 添加NetworkX网络图图层
# 初始化GraphRenderer graph_renderer = GraphRenderer() graph_renderer.node_renderer.data_source.data = dict(index=list(G.nodes())) graph_renderer.edge_renderer.data_source.data = dict( start=[edge[0] for edge in G.edges()], end=[edge[1] for edge in G.edges()] ) # 设置节点布局 graph_renderer.layout_provider = StaticLayoutProvider(graph_layout=layout) # 自定义节点样式(可选) graph_renderer.node_renderer.glyph.size = 15 graph_renderer.node_renderer.glyph.fill_color = linear_cmap('index', Viridis256, 0, len(G.nodes())) graph_renderer.edge_renderer.glyph.line_width = 2 graph_renderer.edge_renderer.glyph.line_color = "#666666" # 将网络图渲染器添加到地图Figure plot.renderers.append(graph_renderer)
5. 展示结果
output_file("network_on_map.html") show(plot)
注意事项
- 如果使用谷歌地图(
GMapPlot),需替换为自己的API密钥,坐标转换逻辑保持一致。 - 若使用自定义GeoJSON地图,只需将瓦片地图替换为
GeoJSONDataSource加载的地理数据,添加GraphRenderer的逻辑完全相同。 - 坐标转换的CRS参数需匹配,常用经纬度CRS为
EPSG:4326,墨卡托投影CRS为EPSG:3857。
内容的提问来源于stack exchange,提问作者Daniel Huang
相关产品推荐
相关产品推荐

