J'ai essayé d'utiliser networkx dans python pour transformer une matrice adjacente en un graphique. Mon graphique "pondéré" a environ 8000 nœuds et 14000 arêtes. Existe-t-il une grande forme de mise en page ou d'autres packages, outils pour rendre mon graphique plus beau? J'espère que le résultat est que le poids Edge plus élevé les nœuds se rapprochent. Afin que je puisse analyser les nœuds du cluster.
J'avais essayé toute la mise en page fournie dans le document networkx. J'ai aussi essayé d'utiliser gephi et il n'est toujours pas satisfait de mon idéal. Voici à quoi cela ressemble dans networkx. Il peut montrer tout le cluster mais cela semble un peu terrible pour quelqu'un qui a une phobie intensive:
Voici le code que j'ai utilisé pour dessiner le graphique:
G = nx.Graph()
for i in range(10000):
for j in range(10000):
if mat[i][j] > 10:
G.add_Edge(a[i], a[j], weight=mat[i][j])
pos = nx.nx_pydot.graphviz_layout(G)
plt.figure(figsize=(8, 8))
plt.axis('off')
nx.draw_networkx(G, pos=pos, with_labels=False, node_size=25, edgecolors='black', Edge_color='b')
plt.show()
Dans le contexte de votre question, vous avez trois façons de visualiser un graphique:
Nous passerons en revue ces façons une par une:
Vous avez 8000 nœuds et 14000 arêtes dans votre graphique. Imaginons que vous n'ayez qu'à dessiner des nœuds sans arêtes. Ainsi, pour un affichage FullHD moyen, vous aurez:
1920 * 1080 / 8000 = 259
Pixels par nœud. C'est:
sqrt(259) = 17
Un 17 × 17 px. nœud si vous allez carreler tout l'affichage avec des nœuds. Si vous souhaitez dessiner des étiquettes de nœuds, vous aurez:
17 - 1 * 2 (outer node borders) - 1 * 2 (inner node borders) = 13×13
carré. La police la plus petite possible (je ne parlerai pas des polices ésotériques ) a une taille de 3×3(+1)
donc vous ne pouvez pas stocker plus de 9 caractères par nœud.
Cela ressemble à ceci:
Et nous n'avons toujours pas dessiné les bords du graphique! Si nous voulons le faire, nous utiliserons:
1920 * 1080 / (8000 + 14000) = 94
pixels par élément graphique, et:
sqrt(94) = 9.7
- 9×9
px. nœuds, il est donc presque impossible d'avoir même des étiquettes simples sur eux.
Je pense qu'il est évident maintenant que l'ensemble du graphique sur l'écran unique ressemblera toujours à un désordre horrible. Ce n'est donc pas une option pour dessiner votre graphique de cette façon.
Si nous ne pouvons pas dessiner le graphique sur un écran, nous pouvons ratisser nos cerveaux et inventer une issue - pour le dessiner sur plusieurs écrans! Nous pouvons le faire de deux manières:
Dans le cas de matplotlib, nous créons une très grande figure (avec l'argument figsize) puis importons notre graphique dans une image (avec plt.savefig):
import networkx as nx
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(40, 40))
G = nx.fast_gnp_random_graph(300, 0.02, seed=1337)
nx.draw(G, node_size=30)
plt.axis('equal')
plt.show()
fig.savefig('waka.svg')
Nous aurons donc une grande image vectorielle (en voici une petite partie):
Dans ce cas, nous pouvons utiliser n'importe quelle disposition de graphique disponible dans networkx.
Une autre façon est d'utiliser la bibliothèque externe Graphviz qui dessinera notre graphique. Honnêtement, dans ce cas, networkx va simplement convertir le graphique en fichier .dot
Et l'envoyer à Graphviz. Le principal inconvénient est que vous ne pouvez pas contrôler la façon dont Graphviz dessinera votre graphique. Mais il a de très bonnes dispositions, donc le résultat sera acceptable.
Utilisez ce code Python pour générer le fichier .dot
:
import networkx as nx
G = nx.fast_gnp_random_graph(300, 0.02, seed=1337)
nx.nx_agraph.write_dot(G, './waka.dot')
puis utilisez Graphviz:
dot -Tsvg waka.dot >waka.svg
ou pour les graphes non dirigés:
neato -Tsvg waka.dot -Goverlap=false >waka.svg
donc l'image résultante ressemblera à ceci (voici aussi une petite partie de l'image entière):
Graphviz possède une énorme quantité d'options différentes afin que vous puissiez transformer votre graphique en le regardant presque comme vous le souhaitez.
Dans votre graphique, vous avez quelque chose comme un composant géant connecté ( GCC ) et de nombreux petits sous-graphiques. L'image est d'environ 580 × 580 et GCC est d'environ 290 × 290, donc GCC utilise:
(290 × 290) ÷ (580 × 580) × 100 = 25%
De votre toile. Si vous ne gardez que GCC, vous aurez 4 fois plus d'espace pour dessiner! Dans ce cas, vous pouvez dessiner un autre composant connecté sur une autre image.
Vous ne pouvez conserver que GCC avec un code comme celui-ci:
import networkx as nx
G = nx.fast_gnp_random_graph(300, 0.01, seed=1337)
gcc = max(nx.connected_components(G), key=lambda x: len(x))
H = G.subgraph(gcc)
nx.draw(G, node_size=30, node_color='red')
dessinera le graphique d'origine:
Et avec cette dernière ligne:
nx.draw(H, node_size=30, node_color='red')
il attirera uniquement le CCG:
Que pouvez-vous faire d'autre avec votre graphique: