Graphviz / PyGraphviz的有向图网络布局采用NetworkX式弹簧模型。

3
NetworkX主要用于图形分析,PyGraphviz主要用于绘图,它们被设计成可以一起工作。然而,至少在一个方面,NetworkX的图形绘制(通过MatPlotLib)优于PyGraphviz的图形绘制(通过Graphviz),即NetworkX具有针对有向图的弹簧布局算法(可通过spring_layout函数访问),而PyGraphviz有多个弹簧布局算法(可通过neato程序和其他方式访问),将有向图布置为无向图。唯一真正处理图中方向的Graphviz/PyGraphviz布局程序是dot,但dot创建的是分层布局,而不是力导向布局。
下面是一个示例,展示了有向图的弹簧布局在NetworkX和PyGraphviz之间的差异:
import networkx as nx
import pygraphviz as pgv
import matplotlib.pyplot as ppt

edgelist = [(1,2),(1,9),(3,2),(3,9),(4,5),(4,6),(4,9),(5,9),(7,8),(7,9)]

nxd = nx.DiGraph()
nxu = nx.Graph()
gvd = pgv.AGraph(directed=True)
gvu = pgv.AGraph()

nxd.add_edges_from(edgelist)
nxu.add_edges_from(edgelist)
gvd.add_edges_from(edgelist)
gvu.add_edges_from(edgelist)

pos1 = nx.spring_layout(nxd)
nx.draw_networkx(nxd,pos1)
ppt.savefig('1_networkx_directed.png')
ppt.clf()

pos2 = nx.spring_layout(nxu)
nx.draw_networkx(nxu,pos2)
ppt.savefig('2_networkx_undirected.png')
ppt.clf()

gvd.layout(prog='neato')
gvd.draw('3_pygraphviz_directed.png')

gvu.layout(prog='neato')
gvu.draw('4_pygraphviz_undirected.png')

1_networkx_directed.png:(http://farm9.staticflickr.com/8516/8521343506_0c5d62e013.jpg)

2_networkx_undirected.png:(http://farm9.staticflickr.com/8246/8521343490_06ba1ec8e7.jpg)

3_pygraphviz_directed.png:(http://farm9.staticflickr.com/8365/8520231171_ef7784d983.jpg)

4_pygraphviz_undirected.png:(http://farm9.staticflickr.com/8093/8520231231_80c7eab443.jpg)

The third and fourth images drawn are almost identical except for the arrowheads. Meanwhile, the first and second images differ in layout due to NetworkX's random element when using the spring_layout. However, it is noticeable that regardless of randomness, the algorithm tries to place nodes closer to the center of the graph based on their connections. If a graph is directed, nodes with incoming arcs are often considered part of the periphery even if they contain many outgoing arcs. NetworkX's spring_layout is both hierarchical and force-directed, which is helpful for analyzing core/periphery structures in directed graphs. Although most layout algorithms treat directed graphs as undirected, the different treatment of NetworkX is useful for analysis. Is it possible to replicate this using PyGraphviz / Graphviz?

很遗憾,NetworkX的spring_layout(实际上是fruchterman_reingold_layout)函数的文档源代码中的注释并没有提供任何关于NetworkX生成结果的线索。
这是使用PyGraphviz使用NetworkX的spring_layout函数绘制网络的结果(请参见下面我自己的答案)。 5_pygraphviz_plus_networkx.png: (http://farm9.staticflickr.com/8378/8520231183_e7dfe21ab4.jpg)
2个回答

5

好的,我想我搞清楚了,所以我将回答自己的问题。我不认为这个问题可以通过PyGraphviz本身解决。然而,我们可以指示PyGraphviz从NetworkX获取节点位置,但使用感叹号()将它们固定,以防止neato程序实际执行除spring_layout计算出来的节点位置之外的任何操作。添加以下代码行:

for k,v in pos1.iteritems():
    gvd.get_node(k).attr['pos']='{},{}!'.format(v[0]*10,v[1]*10)

gvd.layout(prog='neato')
gvd.draw('5_pygraphviz_plus_networkx.png')

结果并不完美 - 我必须将坐标乘以10,以防止节点重叠绘制(显然是一个临时的解决方案),但它是一种改进,即具有0入度的节点在外部(使用NetworkX布局的优势)以及真正的箭头不会被节点本身吞噬(使用PyGraphviz绘制的好处)。
我知道这不完全是我要求的(即使用PyGraphviz / Graphviz本身的解决方案)。
如果有人能提供更好的解决方案,我将感到高兴!
编辑:没有人提供比上述问题更好的解决方案,因此我将接受自己的答案,以表示它实际上有效。但是,我也会投票支持skyebend的答案,因为尽管它不能解决问题,但对于理解基本问题非常有用。

4
Graphviz还有一种名为fdpsfdp的布局模式,可对节点进行力导向放置,类似于弹簧布局。我不熟悉NetworkX,但似乎gvu.layout(prog='fdp')可以工作?如果NetworkX允许将其他参数传递给Graphviz,则可以调整许多可配置的布局参数,以获得更接近所需布局的效果。请参阅Graphviz文档:http://www.graphviz.org/content/attrs 然而,fdp布局将网络视为无向图。我所知道的大多数“弹簧”布局也将网络视为无向图,因为它们必须将其转换为欧几里得空间(屏幕),其中距离是对称的。一个例外是“磁性”弹簧布局,它还尝试对齐弧,使其指向相似的方向以传达层次结构,类似于neato/dot混合体。
算法实现在如何将有向网络中的网络距离转换为无向权重/距离以优化布局方面也可能有所不同。如果您想更好地控制有向弧的解释方式,则可以明确执行此步骤。

感谢您解释为什么大多数Spring布局将网络视为无向的,但是您提供的解决方案(即使用fdpsfdp而不是neato)并没有解决我的问题(正如您在写下“fdp布局将网络视为无向图”时所承认的那样),并且似乎没有Graphviz布局参数可以产生我想要的效果。我将在上面包含屏幕截图,以便您了解我的意思。(如果NetworkX文档解释了正在发生的事情,那肯定会有所帮助!) - Westcroft_to_Apse
我很好奇NetworkX的spring_layout是否类似于那些“‘磁性’弹簧布局”,它也试图使弧线对齐,以传达层次结构。从我上面链接的图片来看,它似乎并不是试图让弧线指向相同的方向,而是试图让它们指向图形的中心。 - Westcroft_to_Apse
我猜我不清楚您想要实现的图像是什么。我不懂Python,但从您提供的FR布局代码来看,它似乎没有明确处理图形的不对称性,并且只尝试优化“出”链接,这似乎可能会产生奇怪的结果。例如,在您提供的图像中,为什么节点7和8应该比7和9更接近?您提供的pygraphviz布局在我看来更一致和更清晰。 - skyebend
两种方法中哪一种更“清晰”取决于您想要澄清什么。在社交网络分析中,核心与外围是其中一个关键概念,而NetworkX布局清楚地显示了哪些节点属于哪个部分,而各种Graphviz布局则完全模糊了核心-外围结构。从这个角度来看,7和8比7和9更接近并不是一个“奇怪的结果”,而是NetworkX布局对于真实世界数据(而不是我在这里使用的玩具数据)非常有价值的一个例子:7和8处于图形的外围,而9处于核心位置。 - Westcroft_to_Apse
我会点赞你的回答,因为即使它没有解决我的具体问题,但它是一个非常有用的贡献。(很抱歉我没有早点这样做 - 我希望有人会发布一个真正的解决方案,但除了我在自己的答案中提供的权宜之计之外,没有人这样做。) - Westcroft_to_Apse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接