首页 > 解决方案 > 选择考虑边缘标签的 networkx 布局

问题描述

我正在使用draw_networkx_edge_labels函数绘制 networkx 加权图。我的问题是,由于边缘有时会相互交叉,因此从图中并不总是清楚哪个权重属于哪个边缘。例如,在下图中,不清楚 2 是 (1,2) 还是 (3,7) 的权重。

布局]

我目前正在使用neato 布局,它不考虑边缘标签。特别是,这就是我绘制加权图的方式g

layout = nx.nx_pydot.graphviz_layout(g, prog='neato')
nx.draw(g, pos=layout)
edge_labels = nx.get_edge_attributes(g, 'weight')
nx.draw_networkx_edge_labels(g, pos=layout, edge_labels=edge_labels)

我知道我可以使用参数手动控制标签沿边缘的位置label_pos,但我的问题是是否存在一种自动绘制图形的方法,这样边缘标签通常不会发生碰撞(或者使用考虑标签的布局或“整齐地”选择沿边缘的标签位置的方法)。

我并不期待总是有效的东西,但由于我的图表连接相对稀疏,我希望有一种方法至少可以很好地工作。

标签: networkxgraphviz

解决方案


一段时间以来,我一直打算在netgraph中实现这一点,我的 networkx 绘图实用程序的分支。不幸的是,我星期四有一个工作面试,所以我很快就没有时间写这个了。然而,基本思想非常简单,并且已经在一些 R 包中实现,例如ggrepelggnetwork.

基本思想是,在给定节点和边缘的预定和固定布局的情况下,您使用强制导向布局来定位标签。所以:

  1. 使用您选择的布局计算节点布局。

  2. 将每条边划分为许多节点的链,并使用边的源节点和目标节点的已知位置计算“边节点”的位置。这种划分是为了在下面的力导向布局中给每条边一个“质量”。

  3. 对于每条边,添加一个“标签”节点并将其连接到最中心的“边节点”。

  4. 计算一个力导向布局,保持除标签节点之外的所有节点固定(例如spring_layout在networkx中使用)。

您现在应该有不与任何边缘重叠的合理边缘标签坐标。用于plt.annotate绘制边缘和边缘标签之间的连接。


推荐阅读