Как увеличить интервал node для networkx.spring_layout

Рисование графика клики с

import networkx as nx
....
nx.draw(G, layout=nx.spring_layout(G))

производит следующую картину:

enter image description here

Очевидно, что расстояние между узлами (например, длина ребра) необходимо увеличить. Я гуглил это и нашел это предложение здесь:

Для некоторых алгоритмов макета есть параметр scale который может помочь. например

import networkx as nx
G = nx.path_graph(4)
pos = nx.spring_layout(G)  # default to scale=1
nx.draw(G, pos)
pos = nx.spring_layout(G, scale=2)  # double distance between all nodes
nx.draw(G, pos)

Однако параметр scale, похоже, не оказывает никакого влияния.

Какой правильный метод, чтобы получить лучший рисунок?

Ответы

Ответ 1

Хорошо, мой ответ слишком поздно для этого вопроса. Но решение этой проблемы заключается в версии NetworkX версии 1.8, которая еще не выпущена, но доступна через концентратор git.

Для увеличения расстояния между узлами выполните следующие действия:

    pos = nx.spring_layout(G,k=0.15,iterations=20)
    # k controls the distance between the nodes and varies between 0 and 1
    # iterations is the number of times simulated annealing is run
    # default k =0.1 and iterations=50

Измените параметры, чтобы увидеть, как они работают. Но, несмотря на это, нет никакой гарантии, что все узлы не перекрываются.

Ответ 2

Реальный ответ на ваш вопрос заключается в том, что ваш исходный график не является единственным, полностью связанным компонентом. Это три отдельных графика.

То, что происходит, - это то, что три части разлетаются в бесконечность, что при повторном масштабировании делает каждый компонент похожим на крошечный шарик.

Алгоритм spring_layout определяет силу отталкивания между всеми узлами (антигравитация) и силу притяжения только между связанными узлами ("пружинами").

Таким образом, если график не связан, отдельные части улетят от силы отталкивания, так как их ничто не связывает. Есть два варианта: изменить закон силы (отредактировать код networkx) или нанести на график компоненты отдельно.

Вот как добавить силу, которая притягивает все узлы к центру диаграммы. Добавьте последнюю строку этого фрагмента кода в def _fruchterman_reingold в layouts.py:

# displacement "force"
displacement = np.einsum('ijk,ij->ik',
                         delta,
                         (k * k / distance**2 - A * distance / k))
# ADD THIS LINE - prevent things from flying off into infinity if not connected
displacement = displacement - pos / ( k * np.sqrt(nnodes))

Эта единственная строка кода позволяет вам создавать диаграммы вроде: enter image description here, а не enter image description here. Однако "лучший" способ справиться с этим - составить схему компонентов по отдельности.

Вы можете перебирать компоненты, отображая их на отдельных графиках, с помощью функций, описанных здесь.

Смотрите этот вопрос GitHub для дальнейшего обсуждения.

Ответ 3

Я использовал параметр оптимального расстояния компоновки Kamada Kawai и установил расстояние между несвязанными компонентами на максимальное расстояние на графике. Возможно, есть лучший способ использования словарей, но это довольно просто:

df = pd.DataFrame(index=G.nodes(), columns=G.nodes())
for row, data in nx.shortest_path_length(G):
    for col, dist in data.items():
        df.loc[row,col] = dist

df = df.fillna(df.max().max())

layout = nx.kamada_kawai_layout(G, dist=df.to_dict())