【问题标题】:Interface between networkx and igraphnetworkx 和 igraph 之间的接口
【发布时间】:2014-06-07 19:03:44
【问题描述】:

我使用 networkx 已经有很长一段时间了,直到最近我开始研究社区检测时,它已经很好地满足了我的目的,而且只进行了很少的调整。相比之下,igraph Python 包似乎具有更广泛的社区检测方法实现(甚至与添加了 Thomas Aynaud 社区包的 networkx 相比)。我只是想知道是否有任何现有的、经过测试的 API 可以轻松地将 networkx 图转换为 igraph 结构,所以我可以利用 igraph 在这方面提供的强大功能?

非常感谢您的友好回答。

【问题讨论】:

    标签: python networkx igraph


    【解决方案1】:

    Networkx 和 python-igraph 都支持广泛的读/写算法(networkxpython-igraph)。

    至少有两种格式(GML 和 pajek)在两者之间似乎很常见,尽管我没有尝试过。

    【讨论】:

    • 感谢安德鲁的快速回答。事实证明,在 iGraph 中仅重构 NetwrokX 图的拓扑结构相当简单——棘手的一点是节点和边属性。但这足以进行社区检测:)
    【解决方案2】:

    将 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),使用边缘列表也更快。

    【讨论】:

    • 此响应可以针对 Python 3 进行更新。zip 不再支持下标。
    • @AryaMcCarthy,完成。我一直很高兴地使用 Python 2,但最近遇到了一些仅对 Python 3 完全支持的包,所以是时候准备切换了。 :)
    【解决方案3】:

    当我尝试在 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())
    

    如果给定 G,一个 nx 对象,但需要一个 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())
    

    (也发布了here

    【讨论】:

      【解决方案4】:

      GMLPajek 旁边,这是我使用 GraphML 传输图表的方式。 Edgelist 也可以,但主要缺点是它会丢弃节点标识符。

      我使用 R - iGraph 导出了我的无向图(参见 python igraph 中的类似函数)

      write_graph(igraphNetwork, exportFilePath, format = "graphml") exportFilePath 是例如“文件夹/yournetwork.graphml”

      并通过 python - networkX 导入并按节点属性名称重新标记:

      import networkx as nx
      G = nx.read_graphml(exportFilePath)
      G = nx.relabel_nodes(G, nx.get_node_attributes(G, 'name'))
      

      这样我就保留了节点标识符。

      【讨论】:

        【解决方案5】:

        现在就这么简单

        import igraph
        g = igraph.Graph.from_networkx(G)
        

        from_networkx() 的文档可以在here 找到,它的实现源代码在here

        【讨论】:

          猜你喜欢
          • 2019-05-09
          • 1970-01-01
          • 1970-01-01
          • 2016-12-05
          • 1970-01-01
          • 2021-10-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多