J'essaie de créer un graphique de réseau linéaire en utilisant Python
(de préférence avec matplotlib
y networkx
bien qu'il s'intéresse à bokeh
) dont le concept est similaire à celui de l'exemple ci-dessous.
Comment construire ce graphique de manière efficace ( pos
?) en Python en utilisant networkx
? Je veux l'utiliser pour des exemples plus compliqués et j'ai l'impression que coder en dur les positions pour ce simple exemple ne sera pas utile :( . Est-ce que networkx
avez-vous une solution à ce problème ?
Je n'ai vu aucun tutoriel sur la façon dont cela peut être réalisé en networkx
c'est pourquoi je pense que cette question sera une ressource fiable pour la communauté. J'ai parcouru en détail le networkx
tutoriels et rien de tel ne s'y trouve. Les mises en page pour networkx
rendrait ce type de réseau impossible à interpréter sans une utilisation minutieuse des pos
argument... qui je crois est ma seule option. Aucune des mises en page précalculées sur le site de l https://networkx.github.io/documentation/networkx-1.9/reference/drawing.html La documentation semble bien gérer ce type de structure de réseau.
Exemple simple :
(A) chaque clé extérieure est l'itération dans le graphe en se déplaçant de gauche à droite (par exemple, l'itération 0 représente les échantillons, l'itération 1 a les groupes 1 - 3, de même pour l'itération 2, l'itération 3 a les groupes 1 - 2, etc.) (B) Le dictionnaire interne contient le groupement actuel à cette itération particulière, et les poids des groupes précédents qui fusionnent et qui représentent le groupe actuel (ex. iteration 3
tiene Group 1
y Group 2
et pour iteration 4
tous les iteration 3's
Group 2
est entré dans iteration 4's
Group 2
mais iteration 3's
Group 1
a été scindé. La somme des poids est toujours égale à 1.
Mon code pour les connexions avec les poids pour le graphique ci-dessus :
D_iter_current_previous = {
1: {
"Group 1":{"sample_0":0.5, "sample_1":0.5, "sample_2":0, "sample_3":0, "sample_4":0},
"Group 2":{"sample_0":0, "sample_1":0, "sample_2":1, "sample_3":0, "sample_4":0},
"Group 3":{"sample_0":0, "sample_1":0, "sample_2":0, "sample_3":0.5, "sample_4":0.5}
},
2: {
"Group 1":{"Group 1":1, "Group 2":0, "Group 3":0},
"Group 2":{"Group 1":0, "Group 2":1, "Group 3":0},
"Group 3":{"Group 1":0, "Group 2":0, "Group 3":1}
},
3: {
"Group 1":{"Group 1":0.25, "Group 2":0, "Group 3":0.75},
"Group 2":{"Group 1":0.25, "Group 2":0.75, "Group 3":0}
},
4: {
"Group 1":{"Group 1":1, "Group 2":0},
"Group 2":{"Group 1":0.25, "Group 2":0.75}
}
}
C'est ce qui s'est passé quand j'ai fait le graphique en networkx
:
import networkx
import matplotlib.pyplot as plt
# Create Directed Graph
G = nx.DiGraph()
# Iterate through all connections
for iter_n, D_current_previous in D_iter_current_previous.items():
for current_group, D_previous_weights in D_current_previous.items():
for previous_group, weight in D_previous_weights.items():
if weight > 0:
# Define connections using `|__|` as a delimiter for the names
previous_node = "%d|__|%s"%(iter_n - 1, previous_group)
current_node = "%d|__|%s"%(iter_n, current_group)
connection = (previous_node, current_node)
G.add_edge(*connection, weight=weight)
# Draw Graph with labels and width thickness
nx.draw(G, with_labels=True, width=[G[u][v]['weight'] for u,v in G.edges()])
Note : La seule autre façon à laquelle j'ai pensé pour faire ceci serait dans matplotlib
créer un nuage de points où chaque coche représente une itération (5, y compris les échantillons initiaux), puis relier les points les uns aux autres avec des pondérations différentes. Il s'agirait d'un code assez compliqué, surtout si l'on essayait d'aligner les bords des marqueurs avec les connexions... Cependant, je ne suis pas sûr que cette méthode et celle de l'analyse des données soient compatibles. networkx
est la meilleure façon de le faire ou s'il existe un outil (par ex. bokeh
o plotly
) qui est conçu pour ce type de tracé.