web-dev-qa-db-fra.com

Comment augmenter l'espacement des nœuds pour networkx.spring_layout

Dessiner un graphique de clique avec

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

produit l'image suivante:

enter image description here

De toute évidence, l'espacement entre les nœuds (par exemple, la longueur du bord) doit être augmenté. J'ai googlé ceci et trouvé cette suggestion ici:

Pour certains des algorithmes de disposition, il existe un paramètre scale qui pourrait aider. par exemple.

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)

Cependant, le paramètre scale ne semble pas avoir d'effet.

Quelle est la bonne méthode pour obtenir un meilleur dessin?

29
clstaudt

D'accord, ma réponse est trop tard pour cette question. Mais la solution à ce problème réside dans la version NetworkX 1.8 qui n'est pas encore sortie, mais qui est disponible via git hub.

Procédez comme suit pour augmenter la distance entre les nœuds:

    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

Ajustez ces paramètres pour voir comment cela fonctionne. Mais malgré cela, il n'y a aucune garantie que tous les nœuds ne se chevauchent pas

32
Vikram

La réponse réelle à votre question est que votre graphique d'origine n'est pas un seul, composant entièrement connecté . Il s'agit de trois graphiques distincts.

Ce qui se passe, c'est que les trois pièces s'envolent à l'infini, ce qui, lors de la mise à l'échelle, fait ressembler chaque composant à une petite goutte.

L'algorithme spring_layout spécifie une force de répulsion entre tous les nœuds (anti-gravité), et une force d'attraction entre uniquement nœuds connectés (les "ressorts").

Ainsi, si le graphique n'est pas connecté, les pièces individuelles s'éloigneront de la force répulsive car il n'y a rien qui les relie. Il existe deux options: modifier la loi de force (modifier le code networkx) ou représenter graphiquement les composants séparément.

Voici comment ajouter une force qui attire tous les nœuds au centre du graphique. Ajoutez la dernière ligne de cet extrait de code à def _fruchterman_reingold in 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))

Cette seule ligne de code vous permet de créer des graphiques comme: enter image description here plutôt que enter image description here Cependant, la "meilleure" façon de résoudre ce problème est de représenter séparément les composants.

Vous pouvez parcourir les composants, les tracer dans des tracés séparés, avec les fonctions décrites ici .

Voir ce numéro de github pour plus de discussion.

5
OrangeSherbet

J'ai utilisé le paramètre de distance optimale de la disposition Kamada Kawai et j'ai défini la distance entre les composants non connectés à la distance maximale dans le graphique. Il existe probablement une meilleure façon de connecter les dictionnaires, mais c'est assez simple:

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())
3
James Houghton