简体   繁体   中英

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.

There is a solution for generating a tooltip when hovering over nodes ( adding tooltip for nodes in python networkx graph ). 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:

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. 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.

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

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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