在networkx/igraph中指定边长(Python)
我想用手头的数据来可视化一个网络,并希望能按照特定的边长来绘制它们。我使用的是Python,尝试过networkx和igraph来绘图,但它们似乎都只设置了固定的边长。
a.) 我在代码上是不是做错了,还是这些库本身就不支持呢?怎样才能在networkx或igraph中正确实现指定的边长?
b.) 如果networkx和igraph做不到,那你能推荐其他什么库吗?(最好是能处理超过八万节点的。)
谢谢!
2 个回答
3
据我所知,networkx和igraph这两个库没有可以根据给定的边长来推测节点位置的布局函数。不过,有一个叫做netgraph的Python库,它可以帮助我们更好地可视化网络,并且实现了我们想要的功能,可以根据几何布局来确定节点的位置。在下面的例子中,我使用边列表来表示网络,但netgraph也可以接受networkx、igraph和graph-tool的图对象。
#!/usr/bin/env python
import matplotlib.pyplot as plt
from netgraph import Graph # pip install netgraph OR conda install -c conda-forge netgraph
# right triangle
edge_length = {
(0, 1) : 0.3,
(1, 2) : 0.4,
(2, 0) : 0.5,
}
edges = list(edge_length.keys())
fig, ax = plt.subplots()
Graph(edges, edge_labels=edge_length, node_layout='geometric',
node_layout_kwargs=dict(edge_length=edge_length), ax=ax)
ax.set_aspect('equal')
plt.show()
如果你只想要节点的位置,但不想用netgraph来绘图,你可以使用get_geometric_layout
这个函数来计算节点的位置:
from netgraph import get_geometric_layout
pos = get_geometric_layout(edges, edge_length)
不过,netgraph使用一种非线性优化的方法来根据边长推测节点的位置。这种计算的复杂度是节点数量的平方。对于那些可以合理表示为链接图的网络(也就是几百个节点以内),计算时间比较短(少于2秒),但我从来没有尝试过在8万个节点上运行这个过程,我怀疑那样会花费几天的时间才能完成。
8
这个应该可以工作:
import networkx as NX
import pygraphviz as PG
G = PG.AGraph()
nlist = "A B C D E".split()
a, b = "A A B", "B C D"
elist = zip(a.split(), b.split())
G.add_nodes_from(nlist)
G.add_edges_from(elist)
G.node_attr.update(color="red", style="filled")
G.edge_attr.update(color="blue", len="2.0", width="2.0")
print(G.edge_attr)
# returns {'color': 'red', 'width': '', 'len': '2.0'}
# add new edge with custom length (all others have length=2.0):
G.add_edge("C", "E", len="3.0", color="blue", width="2.0")
edge = G.get_edge("C", "E")
print(edge_attr)
# returns {'color': 'blue', 'width': '2.0', 'len': '3.0'}
# and you can confirm that introspection by drawing & printing this graph:
G.draw('somefolderandfilename.png', format='png', prog='neato')
大多数图形绘制算法都使用某种版本的SMACOF,这个算法会调整边的长度;不过,graphviz的布局引擎'neato'(在上面'draw'的第二个参数中提供)应该尽量保持用户设置的边长不变。
我在这里使用的库绝对足够强大,可以处理80,000个节点。