Remove rotation effect when drawing a square grid of MxM nodes in networkx using grid_2d_graph

不羁的心 提交于 2019-12-21 05:01:09

问题


I need to generate a regular graph (also known as lattice network) which has 100x100 nodes. I started off with drawing a 10x10 graph with the following code:

import numpy
from numpy import *
import networkx as nx
from networkx import *
import matplotlib.pyplot as plt

G=nx.grid_2d_graph(10,10)        
nx.draw(G)

plt.axis('off')
plt.show()

but what I get is this:

Is there any way of getting rid of this sort of rotation effect the output has? My final network must look like a chess table, just like this (please ignore the lables):

Also, I need to give each node its ID, ranging from 0 to 9999 (in the case of the 100x100 network). Any idea will be much appreciated!


回答1:


By default, networkx.draw uses a spring layout. Instead, you can provide your own positions with parameter pos. This is actually really simple, since the labels of nodes given networkx.grid_2d_graph actually are a (row, column) tuple:

>>> G=nx.grid_2d_graph(2,2)
[(0, 1), (1, 0), (0, 0), (1, 1)]

Thus you can use a node's name as its position. So you just need to create a dictionary mapping nodes to themselves, and pass that as the position.

pos = dict( (n, n) for n in G.nodes() )

However, since you also want to add node labels, you should use networkx.draw_networkx, which takes a dictionary of custom labels as an optional parameter. You'll need a dictionary mapping nodes to their new labels. Since NetworkX gives each node the label (row, column) by default, we can just label each node with row * 10 + column:

labels = dict( ((i, j), i * 10 + j) for i, j in G.nodes() )

Putting it all together, you get the following code which yields the graph below:

import networkx as nx
import matplotlib.pyplot as plt

N = 10
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() )
labels = dict( ((i, j), i * 10 + j) for i, j in G.nodes() )
nx.draw_networkx(G, pos=pos, labels=labels)

plt.axis('off')
plt.show()

EDIT

Using the suggestion from @AbdallahSobehy, we can label the nodes from left to right and top to bottom.

labels = dict( ((i, j), i + (N-1-j) * 10 ) for i, j in G.nodes() )




回答2:


Clarifications to support @mdml answer (All what is said here is to be referenced to the answer of @mdml)

1- Node keys using nx.grid_2d_graph

The keys given to nodes is done implicitly giving each node a key of (i,j) describing the row and column. To access a node at (0,0) -> G[(0,0)]

2- Labels used for drawing

The labels specified for drawing should be done as follows to abide by the numbering scheme in the question:

labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() ) 

please notice it should be N not 10, so that it is more general as if you changed N the labels will not be the ones you expect. Also, these labels are only for drawing so they have nothing to do with accessing the node.

3- Linking keys to labels

accessing node -> G[(0,0)] refers to node 90 in the drawn graph (Lower left corner in general), G[(1,0)] is the node to the right (91), while G[(0,1)] is the node labelled (80) so take care of this convention because it might not be obvious.

4- To give nodes ID that is equivalent to the ones on the graph

You can use the labels dictionary to add an attribute called id to each node which holds the integer that you see in the drawn figure:

for (i,j) in labels:
    G.node[(i,j)]['id'] = labels[(i,j)]

I created a simple graph with N=2, and I used the lines at points 2 and 3 and I printed out the Id's as follows:

for i in xrange(N):
    for j in xrange(N):
        print 'Node ID at: (%d, %d) = %d'  %(i,j,G.node[(i,j)]['id'])
plt.axis('off')
plt.show()

Result:

Node ID at: (0, 0) = 2
Node ID at: (0, 1) = 0
Node ID at: (1, 0) = 3
Node ID at: (1, 1) = 1



来源:https://stackoverflow.com/questions/33168699/remove-rotation-effect-when-drawing-a-square-grid-of-mxm-nodes-in-networkx-using

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!