Интерфейс между networkx и igraph

Я работаю с networkx уже довольно давно, и он служил моим целям довольно хорошо с минимальными настройками до недавнего времени, когда я начал искать обнаружение сообщества. Для сравнения, пакет igraph Python, похоже, имеет гораздо более широкие реализации методов обнаружения сообщества (даже по сравнению с networkx с пакетом сообщества Томаса Айно). Мне просто интересно, есть ли какой-либо существующий, протестированный API, который позволит легко перевести график networkx в структуру играф, чтобы я мог воспользоваться властью, которую играф предоставляет в этой области?

ваши добрые ответы высоко ценятся.

3 ответов


Networkx и python-igraph поддерживают широкий спектр алгоритмов чтения/записи (networkx, python-igraph).

по крайней мере два формата (GML и pajek), похоже, являются общими между ними, хотя я этого не пробовал.


здесь два способа преобразования графа 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), zip(*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-узлового графика на моей машине:

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

использование списка edge также было несколько быстрее для g = nx.complete_graph(2500).


когда я пытаюсь сохранить имена узлов / ребер как на 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)

конечно, это не полная передача, поскольку другие атрибуты узла, а также передача атрибутов edge отсутствуют, но я надеюсь, что это будет полезно, когда у вас нет их.


более подробная версия, что у вас больше контроля при передаче, от 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())

(также опубликовано здесь)