regina_fallangi
regina_fallangi

Reputation: 2198

How to draw loops-edges in networkx indirected Graph

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:

enter image description here

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

Answers (2)

regina_fallangi
regina_fallangi

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:

enter image description here

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

PilouPili
PilouPili

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()

enter image description here

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

Related Questions