Reputation: 2198
I have the following graph:
graph = {("A","A"): 3, ("A","B"): 4, ("A","C"): 1}
And I am trying to draw a graph that shows a loop in node ("A") labeled with the number 3. The loop should look like the one for node (1) here.
It has to be an indirected graph.
So far I am using this:
import networkx as nx
import matplotlib.pyplot as plt
G=nx.Graph()
for edge in graph:
G.add_edge(edge[0], edge[1])
graph_pos=nx.shell_layout(G)
nx.draw_networkx_nodes(G,graph_pos)
nx.draw_networkx_edges(G,graph_pos)
nx.draw_networkx_labels(G, graph_pos)
nx.draw_networkx_edge_labels(G, graph_pos, edge_labels = graph)
plt.show()
The output is:
As you can see, there is no loop around node "A" even thought there is an edge ("A", "A"). Any idea on how I can make it happen?
EDIT - why not a duplicate?
The question Matplotlib and Networkx - drawing a self loop node is for directed graphs. When you create a graph using G=nx.MultiDiGraph
you can set attributes for the edges using G.graph['edge']
.
Using nx.Graph()
(indirected graph), the results for G.graph['edge']
is an empty dictionary.
The difference between that question and this question is, in essence, that I use nx.Graph
and that question uses nx.MultiDiGraph
.
Upvotes: 4
Views: 5582
Reputation: 2198
P.E. Normand's answer made me take a look at graphviz
and I realised that, if I change the arrowsize
of a directed graph to 0, it looks like an indirected graph. Using that I could reuse the answer in Matplotlib and Networkx - drawing a self loop node, but I still lacked the label edges. Using the answer here I managed to create the following graph:
import networkx as nx
from networkx.drawing.nx_agraph import to_agraph
graph = {("A","A"): 3, ("A","B"): 4, ("A","C"): 1}
G=nx.MultiDiGraph()
# add edges
for edge in graph:
G.add_edge(edge[0], edge[1])
# arrow size: '0' makes it look like an indirected graph
G.graph['edge'] = {'arrowsize': '0', 'splines': 'curved'}
G.graph['graph'] = {'scale': '3'}
A = to_agraph(G)
A.layout('dot')
# set edge labels
for pair in graph:
edge = A.get_edge(pair[0], pair[1])
edge.attr['label'] = str(graph[pair]) + " "
A.draw('test.png')
Here is the graph:
This answer could be a duplicate of the question for directed graphs, I still believe it's worth it to keep with the small tweak for indirected graphs.
Upvotes: 2
Reputation: 2699
From what I gather, the draw functions of networkx do not make any effort drawing self loops. The thing that make me say that is: if you change your script to
import networkx as nx
import matplotlib.pyplot as plt
G=nx.Graph()
graph = {("A","A"): 3, ("A","B"): 4, ("A","C"): 1}
#graph = {("A","B"): 4, ("A","C"): 1}
for edge in graph:
G.add_edge(edge[0], edge[1])
graph_pos=nx.circular_layout(G)
nx.draw_networkx_edge_labels(G, graph_pos, edge_labels = graph)
nx.draw_networkx_nodes(G,graph_pos, alpha=0.1)
nx.draw_networkx_edges(G,graph_pos)
#nx.draw_networkx_labels(G, graph_pos)
plt.show()
you will notice that the edge label is shown. In Networkx it seems that the edges are just lines between vertex. A line between the same point is well… nothing…
So I think you will have no luck with networkx.
However using pygraphviz is your best bet as suggested in Matplotlib and Networkx - drawing a self loop node
From my knowledge graphviz (warning it comes only in 32 bits) (and it's python wrapper pygraphviz which needs graphviz) is still a very good graph visualizer.
After installation you can use the to_agraph function of networkx.drawing.nx_agraph.
Good luck.
Upvotes: 1