FaCoffee
FaCoffee

Reputation: 7929

NetworkX: regular graph created from 2D numpy array yields mismatches

Say you have a 2D numpy array (a raster) like this:

import matplotlib.pyplot as plt
import numpy as np
N=5
np.random.seed(17) #For reproducibility
A=np.random.rand(N,N)

In[1]: A
Out[1]:
array([[ 0.294665  ,  0.53058676,  0.19152079,  0.06790036,  0.78698546],
       [ 0.65633352,  0.6375209 ,  0.57560289,  0.03906292,  0.3578136 ],
       [ 0.94568319,  0.06004468,  0.8640421 ,  0.87729053,  0.05119367],
       [ 0.65241862,  0.55175137,  0.59751325,  0.48352862,  0.28298816],
       [ 0.29772572,  0.56150891,  0.39604744,  0.78870071,  0.41848439]])

Which, when plotted, looks like this:

im=plt.imshow(A,origin="upper",interpolation="nearest",cmap=plt.cm.gray_r)
plt.colorbar(im)

enter image description here

And say that you want to create a 2D graph (a lattice network) where each raster cell corresponds to a node, and the size of each node is the value of the cell:

import networkx as nx
#Turn the matrix into a dictionary with the format {(i,j):value}
dict_of_values={(i,j):A[i][j] for i in range(0,A.shape[0]) for j in range(0,A.shape[1])}

#Create lattice network of the same size as A
G = nx.grid_2d_graph(N,N)

#Make sure the nodes are plotted according to a regular grid
labels=dict(((i,j),i + (N-1-j)*N) for i, j in G.nodes())
nx.relabel_nodes(G,labels,False) #False=relabel the nodes in place
inds=labels.keys()
vals=labels.values()
inds=[(N-j-1,N-i-1) for i,j in inds]
#Create the dictionary of positions for the grid
grid_pos=dict(zip(vals,inds)) #Format: {node ID:(i,j)}

#Look up the value for each node in the matrix A
inverted_grid_pos=dict(zip(inds,vals)) #Format: {(i,j):node ID}
#The values in A for each node come from "dict_of_values"
values=[dict_of_values.get(node) for node in inverted_grid_pos]
exaggerate_values=[300*i for i in values]

#Plot the graph with the size based on the values
plt.figure()
nx.draw(G,pos=grid_pos,with_labels=True,node_size=exaggerate_values)

This script returns a mismatch: the size of the nodes does not match the values in the 2D array. In fact, I expected nodes 2, 12, 17, and 20 to be the largest, but this does not happen.

Where does the mismatch arise?

enter image description here

Upvotes: 1

Views: 1526

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339660

Instead of generating the node sizes from the unordered dictionary you can directly use the transposed array A to get the node sizes.

import matplotlib.pyplot as plt
import numpy as np
import networkx as nx

N=4
np.random.seed(17) #For reproducibility
A=np.random.choice([200,400,800], size=(N,N))
A[3,1] = 1500
im=plt.imshow(A,origin="upper",interpolation="nearest",cmap=plt.cm.gray_r)
plt.colorbar(im)


G = nx.grid_2d_graph(N,N)

labels=dict(((i,j),i + (N-1-j)*N) for i, j in G.nodes())
nx.relabel_nodes(G,labels,False) #False=relabel the nodes in place
inds=labels.keys()
vals=labels.values()
inds=[(N-j-1,N-i-1) for i,j in inds]

#Create the dictionary of positions for the grid
grid_pos=dict(zip(vals,inds)) #Format: {node ID:(i,j)}


#Plot the graph with the size based on the values
plt.figure()
nx.draw(G,pos=grid_pos,with_labels=True,node_size=A.T.flatten())

plt.show()

enter image description here

Upvotes: 1

Related Questions