我正在使用 Bokeh 绘制 NetworkX 图,其中节点 ID、边 ID、边长度、宽度和边坐标如下:
import pandas as pd
import networkx as nx
##Graph data
d = {'Node 1': [54524, 56577, 53689, 55961, 54524],
'Node 2': [56577, 76969, 54524, 56354, 54525],
'len': [51.3, 107.7, 27.7, 32.4, 124.8],
'Stick ID': [27967, 27968, 27969, 27970, 27971],
'D': [55.419, 43.543499999999995, 100.282, 100.282, 100.282],
'start_coord': [(507188.35, 6110791.95),
(507159.94, 6110749.25),
(507212.47, 6110778.24),
(507089.54, 6110904.91),
(507188.35, 6110791.95)],
'end_coord': [(507159.94, 6110749.25),
(507248.37, 6110689.01),
(507188.35, 6110791.95),
(507075.96, 6110933.93),
(507098.76, 6110872.37)]}
df = pd.DataFrame(data=d)
#Build NetworkX graph
G_1=nx.from_pandas_edgelist(df, 'Node 1', 'Node 2', edge_attr=["len", "Stick ID", 'D', 'start_coord', 'end_coord'])
#Convert diameters to meters
df['D'] = df['D']/1000
#GRAPH VISUALIZATION
from bokeh.io import output_file, show
from bokeh.plotting import figure, from_networkx
from bokeh.models import Range1d, Circle, ColumnDataSource, MultiLine, BoxZoomTool, HoverTool, Plot, ResetTool
plot = figure(title="Networkx Integration Demonstration", x_range=(-10.1,10.1), y_range=(-10.1,10.1),
tools="pan,wheel_zoom,save,reset", active_scroll='wheel_zoom', toolbar_location=None)
network_graph = from_networkx(G_1, nx.spring_layout, scale=2, center=(0,0))
#Set node size and color
network_graph.node_renderer.glyph = Circle(size=5, fill_color='skyblue')
#Set edge opacity and width
network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5)
plot.renderers.append(network_graph)
output_file("networkx_graph.html")
show(plot)
如何将 DataFram 中的起始坐标和结束坐标添加到 MultiLine 中,以便各行相应定位? (由于坐标为 500、600,中心应该更改吗?)此外,当我将嘴放在边缘上时,我希望看到边缘 Len、Stick ID 和 D。我该如何添加它?
您可以将您想要的任何布局传递给
from_networkx
函数。
它可以是一个networkx布局(在您使用的代码中nx.spring_layout
)或将节点映射到坐标的字典(请参阅文档here)。
在设置悬停工具方面,您可以使用:
hover = HoverTool(tooltips=[("len","@len"),("Stick ID","@Stick_ID"), ("D","@D")],renderers=[network_graph.edge_renderer],show_arrow=False)
要确保将鼠标悬停在边缘时显示工具提示,请确保将
renderers
设置为 [network_graph.edge_renderer]
。查看更多 SO 示例此处。
总的来说,代码看起来像这样:
import pandas as pd
import networkx as nx
import numpy as np
##Graph data
d = {'Node 1': [54524, 56577, 53689, 55961, 54524],
'Node 2': [56577, 76969, 54524, 56354, 54525],
'len': [51.3, 107.7, 27.7, 32.4, 124.8],
'Stick_ID': [27967, 27968, 27969, 27970, 27971],
'D': [55.419, 43.543499999999995, 100.282, 100.282, 100.282],
'start_coord': [(507188.35, 6110791.95),
(507159.94, 6110749.25),
(507212.47, 6110778.24),
(507089.54, 6110904.91),
(507188.35, 6110791.95)],
'end_coord': [(507159.94, 6110749.25),
(507248.37, 6110689.01),
(507188.35, 6110791.95),
(507075.96, 6110933.93),
(507098.76, 6110872.37)]}
df = pd.DataFrame(data=d)
#Build NetworkX graph
G_1=nx.from_pandas_edgelist(df, 'Node 1', 'Node 2', edge_attr=["len", "Stick_ID", 'D', 'start_coord', 'end_coord'])
pos_1={d['Node 1'][i]:d['start_coord'][i] for i in range(len(d['Node 1']))} #getting positions of starting nodes
pos_2={d['Node 2'][i]:d['end_coord'][i] for i in range(len(d['Node 2']))} #getting positions of ending nodes
pos= {**pos_1, **pos_2} #concatenating the two dictionary removes overlaps
#Convert diameters to meters
df['D'] = df['D']/1000
#GRAPH VISUALIZATION
from bokeh.io import output_file, show
from bokeh.plotting import figure, from_networkx
from bokeh.models import Range1d, Circle, ColumnDataSource, MultiLine, BoxZoomTool, HoverTool, Plot, ResetTool
plot = figure(title="Networkx Integration Demonstration",tools="pan,wheel_zoom,save,reset",active_scroll='wheel_zoom', toolbar_location=None) #removed previous xlims and ylims
network_graph = from_networkx(G_1, pos, scale=1)
#Set node size and color
network_graph.node_renderer.glyph = Circle(size=20, fill_color='skyblue')
#Set edge opacity and width
network_graph.edge_renderer.glyph = MultiLine(line_alpha=1,line_width=2)
hover = HoverTool(tooltips=[("len","@len"),("Stick ID","@Stick_ID"), ("D","@D")],renderers=[network_graph.edge_renderer],show_arrow=False)
plot.renderers.append(network_graph)
plot.tools.append(hover)
output_file("networkx_graph.html")
show(plot)
下面是悬停的样子: