Plotting isolated nodes in NetworkX - python

import networkx as nx
import numpy as np
from scipy.sparse import coo_matrix #coordinate sparse matrices
A = np.zeros([4,4])
A[0,1] = A[1,2] = 1
S = coo_matrix(A)
edges = np.r_[[S.row], [S.col]].T
G = nx.Graph()
G.add_edges_from(edges)
nx.draw(G)
When I run that script, I get this:
But there are four nodes. How can I get the isolated fourth node to show?

By only adding the edges to the graph, networkx has no way of knowing about the additional vertices; all it's doing is adding the vertices of each edge that you're providing. If, instead, you explicitly add all vertices, then you're good to go:
G = nx.Graph()
G.add_nodes_from(range(len(A)))
G.add_edges_from(edges)
nx.draw(G)

Related

Combine edges when node degree is n in networkx

I have an undirected graph as follows:
import networkx as nx
import matplotlib.pyplot as plt
l = [('1','2'),('2','3'),('3','4'),('3','5'),('1','6'),('6','7'),('6','8'),('9','8')]
G=nx.Graph()
G.add_edges_from(l)
nx.draw_networkx(G,with_labels=True)
plt.show()
I want to combine edges when node satisfies degree=n(like 2). I need remove node 1,2 and 8,and connect 3-6 and 6-9 in my example. So I expect the results to be as follows.
How can I do it? Thanks in advaence
import networkx as nx
import matplotlib.pyplot as plt
l = [('1','2'),('2','3'),('3','4'),('3','5'),('1','6'),('6','7'),('6','8'),('9','8')]
G=nx.Graph()
G.add_edges_from(l)
# Select all nodes with only 2 neighbors
nodes_to_remove = [n for n in G.nodes if len(list(G.neighbors(n))) == 2]
# For each of those nodes
for node in nodes_to_remove:
# We add an edge between neighbors (len == 2 so it is correct)
G.add_edge(*G.neighbors(node))
# And delete the node
G.remove_node(node)
nx.draw(G,with_labels=True)

Draw a scale-free network in a lattice

I want to generate graph form an adjacency list but I am not happy with how the nodes are positioned. I want them to be positioned according to a pre-defined scheme which resembles a regular grid with arbitrary coordinates x and y, while still maintaining the scale-free features. Let me give an example: A barabasi-albert network with node 1 located at x_1 = 0.6 and y_1 = 0.5, node 2 located at x_2 = -0.5 and y_2 = 1 ... and so on. I have a list of coordinates of each node.
Have a look at the pos parameter of draw_networkx_XXX functions here.
It can be used like this:
import networkx as nx
import matplotlib.pyplot as plt
from random import randint,seed;
seed(1)
nodes = list(range(5))
edges = [ (nodes[i-1],nodes[i]) for i in range(1,len(nodes)) ]
# here we can set the coordinates to our liking
positions = { node:(randint(0,9),randint(0,9)) for node in nodes }
G=nx.Graph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)
nx.draw_networkx(G,pos=positions, with_labels=False, node_size=100)
plt.show()
[Edit]
Here's how we can build the graph from the adjancency list and assign real values to node positions.
import networkx as nx
import matplotlib.pyplot as plt
from random import randint,seed
from pprint import pprint
seed(0)
edges = [ (randint(0,5),randint(0,5)) for i in range(5) ]
G=nx.Graph()
# nodes added automatically with add_edges_from
G.add_edges_from(edges)
# here we can set positions to our liking
positions = { node: (round((5-randint(0,9))/7.0,2)
, round((5-randint(0,9))/7.0,2)) for node in G.nodes }
pprint({ "edges:": edges, "nodes:":list(G.nodes), "positions:":positions }, width=100)
nx.draw_networkx(G, pos = positions, with_labels=False, node_size=100)
plt.show()
Using positions from a csv file is straightforward.
The pos parameter is really supposed to be a dict with node names as keys (I edited the first snippet to reflect that).
So, if we have a csv file with node names and positions, we just build a dict from it and supply the dict for pos.

Joining two networkx graphs on a single edge

I need a graph with N clusters, that somewhat represents the structure of social networks. I planned to go about this by creating N graphs with barabasi albert structure, and then connecting them by a single node.
import networkx as nx
a = nx.barabasi_albert_graph(10,2)
b = nx.barabasi_albert_graph(10,2)
nx.draw(a)
nx.draw(b)
what I want is them connected like this:
But I cannot see or find any simple way of doing this, are there any networkX functionality that can do just this?
Joining two graphs by edge is really simple:
import matplotlib.pyplot as plt
import networkx as nx
a = nx.barabasi_albert_graph(10,2)
b = nx.barabasi_albert_graph(10,2)
c = nx.union(a,b, rename=('a-', 'b-'))
c.add_edge('a-0', 'b-0')
nx.draw_networkx(c,with_labels=True,node_size=500)
plt.show()
And if you want to merge graphs on a common node (this is stated in your question contrary to the title), you can do this:
import matplotlib.pyplot as plt
import networkx as nx
a = nx.barabasi_albert_graph(10,2)
b = nx.barabasi_albert_graph(10,2)
a= nx.relabel_nodes(a, { n: str(n) if n==0 else 'a-'+str(n) for n in a.nodes })
b= nx.relabel_nodes(b, { n: str(n) if n==0 else 'b-'+str(n) for n in b.nodes })
c = nx.compose(a,b)
nx.draw_networkx(c,with_labels=True,node_size=500)
plt.show()

Plot bipartite graph using networkx in Python [duplicate]

This question already has answers here:
Bipartite graph in NetworkX
(4 answers)
Closed 7 years ago.
I have an n1-by-n2 bi-adjacency matrix A of a bipartite graph. The matrix A is a scipy.sparse csc matrix. I would like to plot the bipartite graph using A in networkx. Assume that the nodes are colored according to their class labels called node_class. I could do the following:
import networkx as nx
G = nx.from_numpy_matrix(A)
graph_pos = nx.fruchterman_reingold_layout(G)
degree = nx.degree(G)
nx.draw(G, node_color = node_class, with_labels = False, node_size = [v * 35 for v in degree.values()])
The above code works fine for a square dense adjacency matrix. However not for a non-square bi-adjacency matrix A. The error is:
'Adjacency matrix is not square.'
Moreover the matrix A I have is a scipy.sparse matrix` because it is very large and have lots of zeros. So I would want to avoid making an (n1+n2)-by-(n1+n2) adjacency matrix by stacking A and adding zeros.
I checked the documentation of NetworkX for bipartite graphs, it does not mention how to plot bi-partite graph using bi-adjacency matrix, or create a graph using bi-adjacency sparse matrix. If someone could tell me how to plot the bipartite graph, that would be great!
I don't believe there is a NetworkX function that creates a graph from a biadjacency matrix, so you'll have to write your own. (However, they do have a bipartite module you should check out.)
Here's one way to define a function that takes a sparse biadjacency matrix and converts it to a NetworkX graph (see the comments for explanation).
# Input: M scipy.sparse.csc_matrix
# Output: NetworkX Graph
def nx_graph_from_biadjacency_matrix(M):
# Give names to the nodes in the two node sets
U = [ "u{}".format(i) for i in range(M.shape[0]) ]
V = [ "v{}".format(i) for i in range(M.shape[1]) ]
# Create the graph and add each set of nodes
G = nx.Graph()
G.add_nodes_from(U, bipartite=0)
G.add_nodes_from(V, bipartite=1)
# Find the non-zero indices in the biadjacency matrix to connect
# those nodes
G.add_edges_from([ (U[i], V[j]) for i, j in zip(*M.nonzero()) ])
return G
See an example use case below, where I use nx.complete_bipartite_graph to generate a complete graph:
import networkx as nx, numpy as np
from networkx.algorithms import bipartite
from scipy.sparse import csc_matrix
import matplotlib.pyplot as plt
RB = nx.complete_bipartite_graph(3, 2)
A = csc_matrix(bipartite.biadjacency_matrix(RB, row_order=bipartite.sets(RB)[0]))
G = nx_graph_from_biadjacency_matrix(A)
nx.draw_circular(G, node_color = "red", with_labels = True)
plt.show()
And here's the output graph:
Here is a simple example:
import networkx as nx
import matplotlib.pyplot as plt
from networkx.algorithms import matching
%matplotlib inline
ls=[
[0,0,0,1,1],
[1,0,0,0,0],
[1,0,1,0,0],
[0,1,1,0,0],
[1,0,0,0,0]
]
g = nx.Graph()
a=['a'+str(i) for i in range(len(ls))]
b=['b'+str(j) for j in range(len(ls[0]))]
g.add_nodes_from(a,bipartite=0)
g.add_nodes_from(b,bipartite=1)
for i in range(len(ls)):
for j in range(len(ls[i])):
if ls[i][j] != 0:
g.add_edge(a[i], b[j])
pos_a={}
x=0.100
const=0.100
y=1.0
for i in range(len(a)):
pos_a[a[i]]=[x,y-i*const]
xb=0.500
pos_b={}
for i in range(len(b)):
pos_b[b[i]]=[xb,y-i*const]
nx.draw_networkx_nodes(g,pos_a,nodelist=a,node_color='r',node_size=300,alpha=0.8)
nx.draw_networkx_nodes(g,pos_b,nodelist=b,node_color='b',node_size=300,alpha=0.8)
# edges
pos={}
pos.update(pos_a)
pos.update(pos_b)
#nx.draw_networkx_edges(g,pos,edgelist=nx.edges(g),width=1,alpha=0.8,edge_color='g')
nx.draw_networkx_labels(g,pos,font_size=10,font_family='sans-serif')
m=matching.maximal_matching(g)
nx.draw_networkx_edges(g,pos,edgelist=m,width=1,alpha=0.8,edge_color='k')
plt.show()

How do I get nodes from the specific edge in the networkx?

I want to compare nodes of different edges in the graph. How can I get the nodes(n1 and n2) from the edge(n1,n2)?
An edge in NetworkX is defined by its nodes, so I'm not really sure what you're asking here. A specific edge in the graph is just a tuple of nodes, with an optional weighting.
import networkx as nx
g = nx.Graph()
g.add_edge(1,2)
g.add_edge(2,3)
g.edges()
gives
[(1, 2), (2, 3)]
As you can see, the list of edges explicitly provides the nodes of each edge.
Update: Does this do what you want?
#!/usr/bin/python
import networkx as nx
import random
g = nx.Graph()
g.add_edges_from([(1,2),(2,3),(1,4),(2,5)])
random_edge = random.choice(g.edges())
print 'Randomly selected edge is:', random_edge
print 'Nodes are', random_edge[0], 'and', random_edge[1]
The answer to what I think was the intended question is:
graph = networkx.read_graphml('some_fully_loaded_graph.graphml')
edge0 = list(graph.edges(data=True))[0]
subgraph = graph.edge_subgraph([edge0[:2]])
nodes0 = list(subgraph.nodes(data=True))

Categories