繁体   English   中英

在 python networkx 图中为节点添加工具提示

[英]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

这是在 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM