繁体   English   中英

使用 networkx 和 matplotlib (Python) 为图形边缘添加工具提示

[英]Add a tooltip for graph edges using networkx and matplotlib (Python)

我在 matplotlib 中绘制了一个网络图,并且希望有一个工具提示,当我将鼠标悬停在边缘上时会显示信息。

有一个解决方案可以在悬停在节点上时生成工具提示( 在 python networkx 图中为节点添加工具提示)。 这可以适应悬停在边缘上吗?

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()

是的,这个例子可以很容易地适应边缘而不是节点。

首先,让我们将属性应用于边缘而不是节点,:

import matplotlib.pyplot as plt
import networkx as nx

G = nx.path_graph(5)
attrs = {(0, 1): {'attr1': 20, 'attr2': 'nothing'}, 
         (1, 2): {'attr2': 3}, 
         (2, 3): {'attr1': 42}, 
         (3, 4): {'attr3': 'hello'}, 
         (4, 5): {'attr1': 54, 'attr3': '33'}}
nx.set_edge_attributes(G, attrs)

现在,当我们 plot 图形时,我们要记录边的位置,而不是节点:

fig, ax = plt.subplots()
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos=pos, ax=ax)
edges = 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)

现在,我们只需要更改update_annothover函数来查看图的边缘而不是节点。 因为pos只保存节点的位置,所以我们找到边缘任一端的节点位置的平均值,以便找到边缘的中点。

def update_annot(ind):
    edge = list(G.edges)[ind["ind"][0]]
    xy = (pos[edge[0]] + pos[edge[1]])/2
    annot.xy = xy
    node_attr = {'edge': edge}
    node_attr.update(G.edges[edge])
    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 = edges.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()

结果

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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