简体   繁体   English

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

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

I plotted a network graph in matplotlib and would like to have a tooltip that displays information when I hover the mouse over edges.我在 matplotlib 中绘制了一个网络图,并且希望有一个工具提示,当我将鼠标悬停在边缘上时会显示信息。

There is a solution for generating a tooltip when hovering over nodes ( adding tooltip for nodes in python networkx graph ).有一个解决方案可以在悬停在节点上时生成工具提示( 在 python networkx 图中为节点添加工具提示)。 Can this be adapted for hovering over edges?这可以适应悬停在边缘上吗?

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

Yes, this example can be adapted fairly easily to work for edges instead of nodes.是的,这个例子可以很容易地适应边缘而不是节点。

First, let's apply the attributes to the edges rather than the nodes,:首先,让我们将属性应用于边缘而不是节点,:

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)

Now, we want to record the locations of the edges when we plot the figure, not the nodes:现在,当我们 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)

Now, we just need to alter the update_annot and hover functions to look at the edges of the graph rather than the nodes.现在,我们只需要更改update_annothover函数来查看图的边缘而不是节点。 Because pos only holds the locations of the nodes, we find the average of the location of the nodes at either end of the edge in order to find the edge's midpoint.因为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()

Result结果

在此处输入图像描述

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

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