Strange behavior of networkx draw - python

I try to make the simplest graph in networkx:
import networkx as nx
G = nx.Graph()
G.add_edge('x','y')
and that draw it:
nx.draw_networkx(G)
I have something like this:
which is absolutely wrong, because I created a graph with only two nodes and one edge between it.

I am able to reproduce a figure that is almost identical to this, but to do so I do the following:
G=nx.Graph()
G.add_node('y')
nx.draw_networkx(G)
G.add_edge('x','y')
nx.draw_networkx(G)
The first draw command results in 'y' being at (0,0). The second draw command generates new coordinates for the nodes, but it does not remove the first drawing of node 'y'.
I believe this is probably what you actually did. The code you've provided will behave as you expected it to.

Related

NetworkX Python Diferrent output with same input

Why everytime that a script runs shows a different structure?
Like, the logic it´s the same but it shows diferent order, is there a way to keep the same seed or structure?
Examples of same data but different results:
You can save the position of the nodes in a variable so that the network is represented always in the same way:
First create the graph:
G1 = nx.barabasi_albert_graph(20, 2)
Then run the layout function:
pos = nx.spring_layout(G1)
Then draw the graph like this:
nx.draw(G1, pos=pos)
The nx.spring_layout and other layout functions also allow for a seed value:
nx.spring_layout(G1, seed=31415)
Please note that the order of the nodes in you graph may change each time you create your graph. This may be what is affecting the layout of the graph.
Try to run each function separately.

Separate edge arrows in python/networkx directed graph

I would like to obtain something similar to this:
using the python library networkx. I can generate a similar directed graph using the following code:
import matplotlib.pyplot as plt
import networkx as nx
G = nx.DiGraph()
G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')
nx.draw(G, node_color='w', edgecolors='k', width=2.0, with_labels=True)
plt.show()
which produces:
However, the arrows between the nodes 3 and 4 are superimposed, and it just looks as a single arrow with two heads. Would it be possible to separate them slightly, in order to make more evident the fact that there are two edges over there and not just one? (I know that it can be done using pygraphviz, but I am trying to do it using matplotlib).
I forked the networkx drawing utilities some time ago to work around this and several other issues I have had. The package is called netgraph, and supports drawing of networkx and igraph graph structures (as well as simple edge lists).
It uses matplotlib under the hood, and exposes the created artists so that it easy to manipulate them further even if there is not in-built functionality to do so.
#!/usr/bin/env python
"""
https://stackoverflow.com/questions/61412323/separate-edge-arrows-in-python-networkx-directed-graph
"""
import matplotlib.pyplot as plt
import networkx as nx
import netgraph
G = nx.DiGraph()
G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')
netgraph.draw(G, node_color='w', edge_color='k', edge_width=2.0, node_labels={str(ii) : str(ii) for ii in range(1,5)})
plt.show()
You'll need a MultiDiGraph for multiple edges between two nodes:
G = nx.MultiDiGraph()
G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')
To visualise the network you could use Graphviz which does display parallel edges. You could write the graph in dot and display the graph with graphviz.Source:
from networkx.drawing import nx_pydot
from graphviz import Source
nx_pydot.write_dot(G, 'multig.dot')
Source.from_file('multig.dot')

How to fix position of nodes when using draw_circular in networkx?

I want to draw two graphs are almost same, the only difference is that the second one will have some edges grayed out. And I want nodes in the second graph stay exactly where they are in the first graph.
You need to define the optional pos argument.
In your case using circular layout pos = nx.circular_layout(G). Then you call the plotting commands like nx.draw(G, pos, other_arguments...).

Errors when drawing large Graphs in Networkx

I am trying to visualize a bipartite graph that has about 300,000 nodes total. I'm using my helper function below.
def plot_network(G):
pos = nx.spring_layout(G)
plt.figure(figsize=(10,10))
nx.draw_networkx(G, pos, iterations=20, node_grouping='bipartite',
with_labels=False, node_size = 5)
plot_network(G)
When I try to visualize the Graph in its entirety, the following errors pops up in the IPython cell and the process just hangs there forever:
C:\Users\user\AppData\Roaming\Python\Python36\site-packages\networkx\drawing\layout.py:499: RuntimeWarning:
invalid value encountered in sqrt
I tried visualizing smaller graphs by taking random samples of my data and it has worked...until the samples go above 9000 nodes.
I am not sure how to interpret the error I'm getting, but it seems graph size is a factor. So, is there a limitation on the size of graphs I can visualize in Networkx? Is there anyway I can get around this?
It seems Networkx just couldn't allocate enough space for all the nodes, try increase the figsize or shrink node_size first. If neither of those works, try upgrade the networkx package with pip install networkx --upgrade since it seems like you're not using the latest version of networkx.
In addition to Bubble Bubble's answer suggestions, try using a simpler layout algorithm. Originally I was hitting this error using spring_layout, but I found circular works.
fig, axs = plt.subplots(1,1, figsize=(25,25))
# Define node positions using layout algo
# pos = nx.spring_layout(G, center=(1,1), k=40, iterations=5) # returns error
pos = nx.circular_layout(G)
# draw
nx.draw(G,axis=axs, pos=pos, node_size=1)

NetworkX graphviz_layout not working?

I encountered a problem when trying to plot a graph with many nodes using NetworkX and graphviz_layout. More specifically, the arguments that pass into nx.graphviz_layout do not help at all. Attached is the code I use:
G=some_graph()
import matplotlib.pyplot as plt
plt.figure(figsize=(32,32))
# use graphviz to find radial layout
pos=nx.graphviz_layout(G,prog="dot",
root=1000,
args='-splines=true -nodesep=0.6 -overlap=scalexy'
)
nx.draw(G,pos,
with_labels=True,
alpha=0.5,
node_size=600,
font_size=10
)
plt.savefig("imagenet_layout.png")
No matter how I change "args" in nx.graphviz_layout, the output image would be the same, and all nodes overlap with each other. Could anybody help me with this? Thanks!
For me it seems that in order to give args to the prog you need to use the format '-G' +'argsname=x'. I noticed in the example they give the docs the arg epsilon asG.draw(‘test.ps’,prog=’twopi’,args=’-Gepsilon=1’). So I tried out that pattern as shown below. I just added G in front of the arguments. Now, these arguments vary quite a bit depending on what prog you use, so you definitely want to use 'dot' for what you want to accomplish. You can see all the possible arguments and how they work with each prog here. For my porpoises, I needed to have the nodesep=0.01.
G=some_graph()
import matplotlib.pyplot as plt
plt.figure(figsize=(32,32))
# use graphviz to find radial layout
pos=nx.graphviz_layout(G,prog="dot",
root=1000,
args='-Gsplines=true -Gnodesep=0.6 -Goverlap=scalexy'
)
nx.draw(G,pos,
with_labels=True,
alpha=0.5,
node_size=600,
font_size=10
)
plt.savefig("imagenet_layout.png")
Here is a comparison of my graph with and without the args, with code. First without the args.
A = nx.nx_agraph.to_agraph(G) # convert to a graphviz graph
A.layout(prog='neato') # neato layout
#A.draw('test3.pdf')
A.draw('test3.png' )
With args
A = nx.nx_agraph.to_agraph(G) # convert to a graphviz graph
A.layout(prog='dot') # neato layout
#A.draw('test3.pdf')
A.draw('test3.png',args='-Gnodesep=0.01 -Gfont_size=1', prog='dot' )
SO you can see that the images are different once I got the args to work.
My reading of the documentation for pygraphviz suggests that overlap does not work with dot.
For nodesep :
In dot, this specifies the minimum space between two adjacent nodes in the same rank, in inches.
It's not clear if the overlaps you are observing are between nodes in the same rank or between the ranks. If it is just between ranks, you may want to modify ranksep.
I do see that you are setting the positions, and then later you set the nodesize, and you are making node_size quite a bit larger than the default (600 vs 300). Since it does not know what node_size you are going to use when it finds pos, using a large enough node_size will cause overlap.
So I would recommend setting node_size to be the default, and if overlap remains, setting node_size to be smaller. If you're having issues with the between or within rank separations being out of proportion, then play with ranksep and nodesep.
About “overlap”,do you mean there are nodes drawed last time in current output? If so, add "plt.clf()"after"plt.savefig(****)"!
About the node_size, the default is 300, but the unit is not given in the document. I am using networkx these days too, can you tell me the unit if you know that?

Categories

Resources