Interfaz entre networkx y igraph

He estado trabajando con networkx durante bastante tiempo y ha estado cumpliendo mis propósitos bastante bien con ajustes mínimos hasta hace poco, cuando comencé a analizar la detección de comunidades. En comparación, el paquete igraph Python parece tener implementaciones mucho más amplias de métodos de detección comunitarios (incluso en comparación con networkx con el paquete comunitario de Thomas Aynaud agregado). Me pregunto si hay alguna API probada y existente que permita la fácil traducción de un gráfico de networkx a la estructura igraph, así que puedo aprovechar el poder que igraph proporciona en esta área.

Sus respuestas amables son muy apreciadas.

Networkx y python-igraph son compatibles con una amplia gama de algoritmos de lectura / escritura ( networkx , python-igraph ).

Al menos dos formatos ( GML y pajek) parecen ser comunes entre los dos, aunque no lo he intentado.

Aquí hay dos formas de convertir un gráfico de NetworkX a un 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() 

El uso de la lista de bordes fue algo más rápido para el siguiente gráfico de 2500 nodos en mi máquina: (Tenga en cuenta que el siguiente código es solo para Python 2; actualicé el código anterior para ser compatible con 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 

Usar la lista de bordes también fue algo más rápido para g = nx.complete_graph(2500) .

Cuando trato de almacenar nombres de nodos / bordes tanto en igraph como en nx, esta es mi versión de una sola línea que también transfiere nombres de nodos al transferir desde el objeto igraph, g , a 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()) 

Y a la inversa si se da G, un objeto nx, pero se necesita un objeto igraph:

 g = igraph.Graph.TupleList(G.edges(), directed=True) 

Por supuesto, estos no son una transferencia completa, ya que faltan otros atributos de nodo y también faltan las transferencias de atributos de borde, pero espero que sea útil cuando no los tenga.


Versión más detallada que tiene más control al transferir, de igraph a 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()]) 

De nx a igraph:

 g = igraph.Graph(directed=True) g.add_vertices(G.nodes()) g.add_edges(G.edges()) 

(también publicado aquí )

Junto a GML y Pajek , aquí está cómo transporté mi gráfica usando GraphML . Edgelist también funciona, pero tiene la principal desventaja de que descarta los identificadores de nodo.

Exporté mi gráfico no dirigido usando R – iGraph (vea la función similar en el igraph de python)

write_graph(igraphNetwork, exportFilePath, format = "graphml") con exportFilePath siendo, por ejemplo, “folder / yournetwork.graphml”

E importe a través de python – networkX y vuelva a etiquetar por nombre de atributo de nodo: import networkx as nx G = nx.read_graphml(exportFilePath) G = nx.relabel_nodes(G, nx.get_node_attributes(G, 'name'))

De esta manera mantuve los identificadores de nodo.