python - Networkx 和 Matplotlib : how to access node attributes and show them as annotation

标签 python matplotlib hover networkx

我正在尝试让悬停功能适用于此 networkx matplotlib 图表,但我遇到了一个关键错误问题。我想创建一个节点,其键名称为字符串,并将其作为标签。但是,它看起来像是在 xy=pos[node] 部分调用的悬停函数。以下是其中一些内容的一些输出:

  • 此输出中的 obj 是我打印的节点键。
  • ind 是我将鼠标悬停在节点上。
  • node 是我试图找出节点键和悬停正在寻找的内容之间的链接。
pos: {'A': array([-0.88308537, -0.21952651]), 'B': array([ 0.70105714, -0.78047349]), 'C': array([0.18202824, 1.        ])}

obj: A
obj: B
obj: C
ind: {'ind': array([], dtype=int32)}
ind: {'ind': array([2], dtype=int32)}
node: 2
ind: {'ind': array([2], dtype=int32)}
node: 2
ind: {'ind': array([2], dtype=int32)}

代码如下:

import networkx as nx
import matplotlib.pyplot as plt
from networkx.readwrite import edgelist
import numpy as np

G = nx.DiGraph()

G.add_node("A", attr1=20)
G.add_node("B", attr1=25)
G.add_node("C", attr1=30)

fig, ax = plt.subplots()
pos = nx.spring_layout(G)
print('pos:', pos)

nodes = nx.draw_networkx_nodes(G, pos, node_size=500)

for obj in G.nodes:
    print('obj:', obj)

nx.draw_networkx_edges(G, pos, edgelist=G.edges(), edge_color='black')

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]
    print('node:',node)
    xy = pos[node]
    print('here:', xy)
    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)
        print('ind:',ind)
        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()

错误:

xy = pos[node]
KeyError: 2

看起来它正在尝试查找包含数字而不是字母的 key 。这就是为什么我收到一个关键错误。但我不确定为什么我不能让它接受字符串。

最佳答案

node_index = ind["ind"][0] 是节点列表中的整数索引。 Networkx 使用节点名称将其节点存储在字典中。 G.nodes[2] 给出错误,因为 G.nodes 是一个按节点名称索引的字典。

您可以将G.nodes转换为列表,并在node_index处找到名称:node_name = list(G.nodes)[node_index].使用该名称,您可以找到属性:node_attr = G.nodes[node_name]

要使用悬停注释,我建议 mplcursors图书馆,隐藏了许多内部簿记。

以下是更新后的示例:

import matplotlib.pyplot as plt
import networkx as nx
import mplcursors

G = nx.DiGraph()
G.add_node("A", attr1=20)
G.add_node("B", attr1=25)
G.add_node("C", attr1=30)

fig, ax = plt.subplots()
pos = nx.spring_layout(G)
nodes = nx.draw_networkx_nodes(G, pos, node_size=500, node_color='dodgerblue')

nx.draw_networkx_labels(G, pos, font_color='yellow')
nx.draw_networkx_edges(G, pos, edgelist=G.edges(), edge_color='black')

def update_annot(sel):
    node_index = sel.target.index
    node_name = list(G.nodes)[node_index]
    node_attr = G.nodes[node_name]
    text = node_name + ' ' + '\n'.join(f'{k}: {v}' for k, v in node_attr.items())
    sel.annotation.set_text(text)

cursor = mplcursors.cursor(nodes, hover=True)
cursor.connect('add', update_annot)

plt.show()

networkx with mplcursors

关于python - Networkx 和 Matplotlib : how to access node attributes and show them as annotation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70340499/

相关文章:

python - 带有 PyGObject 自省(introspection) Gtk+ 3 的 GenericTreeModel?

python - 如何发送命令并让 Errbot 私下回复我?

python - 解决 "EOF market not found error"PyPDF2

python - 无法为 matplotlib 子图绘制图例/轴

jquery - 鼠标悬停时添加边框

python - 如何从每个键有多个值的字典中写入 csv 文件?

python - 如何在 Python 中的同一个图上绘制两个不同的间隔时间序列

python - 散点图 : Decreasing spacing between scatter points/x-axis ticks

javascript - 如何在元素附近的适当位置显示提示?

css - 悬停一个元素时更改所有其他元素的样式