【问题标题】:Add a tooltip for graph edges using networkx and matplotlib (Python)使用 networkx 和 matplotlib (Python) 为图形边缘添加工具提示
【发布时间】:2021-06-22 04:41:41
【问题描述】:

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

有一个解决方案可以在将鼠标悬停在节点上时生成工具提示 (adding tooltip for nodes in python networkx graph)。这可以适应悬停在边缘上吗?

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

【问题讨论】:

    标签: python matplotlib networkx


    【解决方案1】:

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

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

    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)
    

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

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

    结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-24
      • 1970-01-01
      • 2019-02-28
      • 2020-05-26
      相关资源
      最近更新 更多