Как увеличить интервал 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))
Эта единственная строка кода позволяет вам создавать диаграммы вроде:
, а не
. Однако "лучший" способ справиться с этим - составить схему компонентов по отдельности.
Вы можете перебирать компоненты, отображая их на отдельных графиках, с помощью функций, описанных здесь.
Смотрите этот вопрос 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())