16
votes

I've been working with networkx for quite some time now and it's been serving my purposes quite well with minimal tweaks until recently when I started looking into community detection. In comparison, the igraph Python package seems to have a much wider implementations of community detection methods (even compared to networkx with Thomas Aynaud's community package added on). I'm just wondering if there's any existing, tested API that would allow easy translation of a networkx graph into the igraph structure, so I can avail myself of the power igraph provides in this area?

Your kind answers are highly appreciated.

5

5 Answers

6
votes

Networkx and python-igraph both support a wide range of read/write algorithms (networkx, python-igraph).

At least two formats (GML and pajek) appear to be common between the two, although I haven't tried this.

14
votes

Here two ways to convert a NetworkX graph to an 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()

Using the edge list was somewhat faster for the following 2500-node graph on my machine: (Note that the code below is Python 2 only; I updated the code above to be Python 2/3 compatible.)

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

Using the edge list was also somewhat faster for g = nx.complete_graph(2500).

5
votes

As I try to store names of nodes/edges on both igraph or nx, this is my one-liner version which also transfers nodes names while transferring from igraph object, g, to 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())

And the reverse way if G, a nx object, is given but an igraph object is needed:

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

Of course these are not complete transfer as other node attributes and also edge attribute transfers are missing but I hope would be useful when you don't have them.


More verbose version that you have more control while transferring, from igraph to 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()])

From nx to igraph:

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

(also posted here)

4
votes

Next to GML, and Pajek, here is how I transported my graph using GraphML. Edgelist works as well, but has the main disadvantage that it discards node identifiers.

I exported my undirected graph using R - iGraph (see similar function in python igraph)

write_graph(igraphNetwork, exportFilePath, format = "graphml") with exportFilePath being e.g. "folder/yournetwork.graphml"

And import via python - networkX and relabel by node attribute name:

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

This way I kept the node identifiers.

0
votes

This is now as easy as

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

Documentation for from_networkx() can be found here and the source code for its implementation here.