Интерфейс между 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())
(также опубликовано здесь)