[英]adding tooltip for nodes in python networkx graph
我使用networkx.DiGraph
創建了一個有向圖,然后使用networkx.draw_spring(graph)
繪制它,因此該圖的所有節點都有一些詳細信息存儲在字典列表中。
如何添加類似“工具提示”的內容以在每個節點上的鼠標 hover 上查看這些詳細信息? 如果這是可能的,如何使這個“工具提示”對所有節點始終可見,而不僅僅是通過懸停?
對於 label 所有節點,您只需要使用annotate
即可。 像這樣的東西
import matplotlib.pyplot as plt
import networkx as nx
G = nx.path_graph(5)
attrs = {0: {'attr1': 20, 'attr2': 'nothing'}, 1: {'attr2': 3}, 2: {'attr1': 42}, 3: {'attr3': 'hello'}, 4: {'attr1': 54, 'attr3': '33'}}
nx.set_node_attributes(G, attrs)
nx.draw(G)
for node in G.nodes:
xy = pos[node]
annot.xy = xy
node_attr = G.nodes[node]
text = '\n'.join(f'{k}: {v}' for k, v in G.nodes[node].items())
text = f'node {node}\n' + text
ax.annotate(text, xy=xy)
這是在 hover 上獲取工具提示的工作示例。 這是基於使用標准 matplotlib 圖的工具提示。 我使用draw_networkx_nodes
來獲取用於懸停和顯示工具提示的對象,而不是使用draw_spring
。 但是您可以使用 spring_layout 手動定義spring_layout
。
import matplotlib.pyplot as plt
import networkx as nx
G = nx.path_graph(5)
attrs = {0: {'attr1': 20, 'attr2': 'nothing'}, 1: {'attr2': 3}, 2: {'attr1': 42}, 3: {'attr3': 'hello'}, 4: {'attr1': 54, 'attr3': '33'}}
nx.set_node_attributes(G, attrs)
fig, ax = plt.subplots()
pos = nx.spring_layout(G)
nodes = nx.draw_networkx_nodes(G, pos=pos, ax=ax)
nx.draw_networkx_edges(G, pos=pos, ax=ax)
annot = ax.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"),
arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)
def update_annot(ind):
node = ind["ind"][0]
xy = pos[node]
annot.xy = xy
node_attr = {'node': node}
node_attr.update(G.nodes[node])
text = '\n'.join(f'{k}: {v}' for k, v in node_attr.items())
annot.set_text(text)
def hover(event):
vis = annot.get_visible()
if event.inaxes == ax:
cont, ind = nodes.contains(event)
if cont:
update_annot(ind)
annot.set_visible(True)
fig.canvas.draw_idle()
else:
if vis:
annot.set_visible(False)
fig.canvas.draw_idle()
fig.canvas.mpl_connect("motion_notify_event", hover)
plt.show()
僅供參考@busybear @sudofix
這僅在您的節點從 0 開始時才有效。
如果你這樣做:
import matplotlib.pyplot as plt
import networkx as nx
nodes = list(range(5))
edges = []
for e1,e2 in zip(nodes[:-1],nodes[1:]):
edges.append((e1,e2))
G = nx.Graph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)
attrs = {}
for node in G.nodes:
attrs[node] = {'attr1': node, 'attr2': 'hello', 'attr3': 33}
並將 rest 保留為
nx.set_node_attributes(G, attrs)
fig, ax = plt.subplots()
pos = nx.spring_layout(G)
nodes = nx.draw_networkx_nodes(G, pos=pos, ax=ax)
nx.draw_networkx_edges(G, pos=pos, ax=ax)
annot = ax.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"),
arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)
def update_annot(ind):
node = ind["ind"][0]
xy = pos[node]
annot.xy = xy
node_attr = {'node': node}
node_attr.update(G.nodes[node])
text = '\n'.join(f'{k}: {v}' for k, v in node_attr.items())
annot.set_text(text)
def hover(event):
vis = annot.get_visible()
if event.inaxes == ax:
cont, ind = nodes.contains(event)
if cont:
update_annot(ind)
annot.set_visible(True)
fig.canvas.draw_idle()
else:
if vis:
annot.set_visible(False)
fig.canvas.draw_idle()
fig.canvas.mpl_connect("motion_notify_event", hover)
plt.show()
一切都很好。
但是,如果您將nodes = list(range(5))
更改為nodes = list(range(1,6))
它不起作用,因為node = ind["ind"][0]
返回 position 中的節點G.nodes
而不是節點的名稱,因此訪問pos[node]
和G.nodes[node]
會得到錯誤的 position(它移動了 1)。
解決方案是創建一個映射
idx_to_node_dict = {}
for idx, node in enumerate(G.nodes):
idx_to_node_dict[idx] = node
並修復 function 以將其用作:
def update_annot(ind):
node_idx = ind["ind"][0]
node = idx_to_node_dict[node_idx]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.