networkx与igraph之间的接口
我已经使用networkx一段时间了,它在我的项目中表现得很好,几乎不需要调整。最近,我开始研究社区检测。相比之下,igraph这个Python包似乎在社区检测方法上有更多的实现(即使是加上Thomas Aynaud的community包的networkx也不如它)。我在想有没有现成的、经过测试的API,可以方便地把networkx的图转换成igraph的结构,这样我就能利用igraph在这方面的强大功能了?
非常感谢大家的热心回答。
5 个回答
除了 GML 和 Pajek,我还用 GraphML 来传输我的图。边列表 也可以用,但它的主要缺点是会丢失节点的标识符。
我使用 R 语言中的 iGraph 导出了我的无向图(在 Python 的 igraph 中也有类似的功能)。
write_graph(igraphNetwork, exportFilePath, format = "graphml")
,其中 exportFilePath 比如可以是 "folder/yournetwork.graphml"。
然后通过 Python 的 networkX 导入,并根据节点属性名称重新标记:
import networkx as nx
G = nx.read_graphml(exportFilePath)
G = nx.relabel_nodes(G, nx.get_node_attributes(G, 'name'))
这样我就保留了节点的标识符。
我在尝试在igraph和nx之间存储节点和边的名称时,写了一个简洁的代码,可以在从igraph对象g
转到nx时,同时转移节点名称:
G = nx.from_edgelist([(names[x[0]], names[x[1]])
for names in [g.vs['name']] # simply a let
for x in g.get_edgelist()], nx.DiGraph())
如果你有一个nx对象G,但需要一个igraph对象,可以用反向的方法:
g = igraph.Graph.TupleList(G.edges(), directed=True)
当然,这些转换并不完整,因为其他节点属性和边属性的转换还没有包含,但我希望在你没有这些属性时,这些代码会对你有帮助。
如果你想在从igraph转到nx时有更多的控制,可以使用下面这个更详细的版本:
G = nx.DiGraph()
names = g.vs['name']
G.add_nodes_from(names)
G.add_edges_from([(names[x[0]], (names[x[1]])) for x in g.get_edgelist()])
从nx转到igraph的代码:
g = igraph.Graph(directed=True)
g.add_vertices(G.nodes())
g.add_edges(G.edges())
(也可以在这里找到)
这里有两种方法可以把NetworkX图转换成igraph:
import networkx as nx, igraph as ig
# create sample NetworkX graph
g = nx.planted_partition_graph(5, 5, 0.9, 0.1, seed=3)
# convert via edge list
g1 = ig.Graph(len(g), list(zip(*list(zip(*nx.to_edgelist(g)))[:2])))
# nx.to_edgelist(g) returns [(0, 1, {}), (0, 2, {}), ...], which is turned
# into [(0, 1), (0, 2), ...] for igraph
# convert via adjacency matrix
g2 = ig.Graph.Adjacency((nx.to_numpy_matrix(g) > 0).tolist())
assert g1.get_adjacency() == g2.get_adjacency()
在我这台机器上,对于这个有2500个节点的图,使用边列表的速度稍微快一些。(注意,下面的代码只适用于Python 2;我已经把上面的代码更新成可以在Python 2和3中都能用。)
In [5]: g = nx.planted_partition_graph(50, 50, 0.9, 0.1, seed=3)
In [6]: %timeit ig.Graph(len(g), zip(*zip(*nx.to_edgelist(g))[:2]))
1 loops, best of 3: 264 ms per loop
In [7]: %timeit ig.Graph.Adjacency((nx.to_numpy_matrix(g) > 0).tolist())
1 loops, best of 3: 496 ms per loop
对于g = nx.complete_graph(2500)
,使用边列表的速度也稍微快一些。
Networkx和python-igraph这两个库都支持很多种读取和写入算法(networkx,python-igraph)。
至少有两种格式(GML和pajek)在这两个库之间是比较常见的,虽然我还没有尝试过。