Labelling the edges in a graph with python igraph - python

I have the adjacency matrix (i.e. a collection of weights) of a directed graph, and I would like to add labels (corresponding to the values of the weights) on the edges in the final plot.
In other words, I would like to obtain something like this.
I'm using python igraph, and my code is as follows:
import numpy as np
import igraph as ig
N = 6
adj_matr = np.random.random((N, N))
g = ig.Graph.Weighted_Adjacency(adj_matr.tolist(), mode=ig.ADJ_DIRECTED, attr="weight", loops=True)
ig.plot(g, "My_Graph.svg", vertex_label=map(str, np.arange(N)))
I have figured out how to set labels on the nodes, but I cannot find anything concrete about the edges (adding edge_label=... in the plot command doesn't work). Do you know how to fix the problem? Thanks in advance for your help!

using vertex_label= is equivalent to g.vs=
so to label your edges, use g.es=:
g.es["label"] = ["A", "B", "C"]
or
g.es["name"] = map(str, np.arange(N))

Related

Is there a specific way to name nodes in a Dataset on Python 3

Hi I am trying to build a graph of a .net dataset using Networkx(Python 3). My dataset consists a total of 40 nodes. I want to label the nodes(from 0 to 39). I have tried using xrange but unable to do so. Are there any specific methods to perform such a task?
Thank you.
I am sharing my code.
import networkx as nx
import matplotlib.pyplot as plt
import scipy as sp
G = nx.read_pajek('E:/Data_sets/football.net')
F = nx.DiGraph(G)
G.add_node(0)
Demands = list(xrange(0 , 5000))
for i in xrange(5000):
G.add_node(Demands[i])
print(nx.info(G))
nx.draw(F)
plt.show()
The code does not lable the nodes at all.
The convert_node_labels_to_integers will do what you're trying to do. If you need the labels in a specific order based on the input data, the relabel_nodes method will allow you to pass in a dictionary to match up new labels with existing labels.
You also need to pass with_labels = True when you use nx.draw in order to actually show the labels on the nodes when the graph is plotted.

Networkx - problem while working big data

I am trying to triangulate a large amount of massive data using Delaunay to scipy.spatial for triangulation and networkx to get the node adjacency relations. My code works very well on small data sets but when I try to introduce volumes of about 2 miollion points I always get the following error:
raise NetworkXError(f"The node {n} is not in the graph.") from e
NetworkXError: The node 1 is not in the graph.
It seems like my graph store the first node and nothing more. When I did my research I found that networkx is well adapted to massive data
Here is my code :
import numpy as np
import networkx as nx
import scipy.spatial
points = np.genfromtxt('las1.xyz', delimiter = ';')
xy= points[:,0:2]
z= points[:,2]
delTri = scipy.spatial.Delaunay(xy)
edges = set()
for n in range(delTri.nsimplex):
edge = sorted([delTri.vertices[n,0], delTri.vertices[n,1]])
edges.add((edge[0], edge[1]))
edge = sorted([delTri.vertices[n,0], delTri.vertices[n,2]])
edges.add((edge[0], edge[1]))
edge = sorted([delTri.vertices[n,1], delTri.vertices[n,2]])
edges.add((edge[0], edge[1]))
pts_neigh = {}
graph = nx.Graph(list(edges))
for i in range(len(xy)):
pts_neigh[i] = list(graph.neighbors(i))
I still get the edges list from my networkx graph but it seems like it fails at the level of constructing the nodes.
I will be so grateful for your help.
Although it's possible to instantiate graph with specific data, the syntax can be a bit complex. An easier option is to explicitly add edges from a list:
graph = nx.Graph()
graph.add_edges_from(list(edges))

Add edge-weights to plot output in networkx from adjacency matrix

I'm generating a random graph and drawing it from the adjacency matrix. I need to be able to add the edge weights.
I looked at Add edge-weights to plot output in networkx and that seems to work fine and is exactly what I'm looking for in the display, but it only works when adding edges individually.
I'm using:
nx.from_numpy_matrix(G, create_using = nx.DiGraph())
And according to the documentation, if the nonsymmetric adjacency matrix has only integer entries (which it does), the entries will be interpreted as weighted edges joining the vertices (without creating parallel edges). So when looking at Add edge-weights to plot output in networkx, they grab the node attributes, grab the label attributes, and draw the edge labels. But I'm unable to grab the attributes. Does anyone know how to display these edges while still using this adjacency matrix?
Thanks in advance!
from random import random
import numpy
import networkx as nx
import matplotlib.pyplot as plt
#here's how I'm generating my random matrix
def CreateRandMatrix( numnodes = int):
def RandomHelper():
x = random()
if x < .70:
return(0)
elif .7 <= x and x <.82:
return(1)
elif .82 <= x and x <.94:
return(2)
else:
return(3)
randomatrix = numpy.matrix([[RandomHelper() for x in range(numnodes)] for y in range(numnodes)])
for i in range(len(randomatrix)):
randomatrix[i,i]=0
return randomatrix
#this generate the graph I want to display edge weights on
def Draw(n = int):
MatrixtoDraw = CreateRandMatrix(n)
G = nx.from_numpy_matrix(MatrixtoDraw, create_using = nx.DiGraph())
nx.draw_spring(G, title="RandMatrix",with_labels=True)
plt.show()
This my attempt at following Add edge-weights to plot output in networkx.
def Draw2(n = int):
MatrixtoDraw = CreateRandMatrix(n)
G = nx.from_numpy_matrix(MatrixtoDraw, create_using = nx.DiGraph())
nx.draw_spring(G, title="RandMatrix",with_labels=True)
pos=nx.get_node_attributes(G,'pos')
labels = nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels)
plt.show()
If I run each line individually on idle I get
>>> nx.get_node_attributes(G,'pos')
{}
>>> nx.get_node_attributes(G,'weight')
{}
Why are they not being grabbed from the graph information generated by the adjacency matrix?

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

Create a weighted graph from an adjacency matrix in graph-tool, python interface

How should I create a graph using graph-tool in python, out of an adjacency matrix?
Assume we have adj matrix as the adjacency matrix.
What I do now is like this:
g = graph_tool.Graph(directed = False)
g.add_vertex(len(adj))
edge_weights = g.new_edge_property('double')
for i in range(adj.shape[0]):
for j in range(adj.shape[1]):
if i > j and adj[i,j] != 0:
e = g.add_edge(i, j)
edge_weights[e] = adj[i,j]
But it doesn't feel right, do we have any better solution for this?
(and I guess a proper tag for this would be graph-tool, but I can't add it, some kind person with enough privileges could make the tag?)
Graph-tool now includes a function to add a list of edges to the graph. You can now do, for instance:
import graph_tool as gt
import numpy as np
g = gt.Graph(directed=False)
adj = np.random.randint(0, 2, (100, 100))
g.add_edge_list(np.transpose(adj.nonzero()))
this is the extension of Tiago's answer for the weighted graph:
adj = numpy.random.randint(0, 10, (100, 100)) # a random directed graph
idx = adj.nonzero()
weights = adj[idx]
g = Graph()
g.add_edge_list(transpose(idx)))
#add weights as an edge propetyMap
ew = g.new_edge_property("double")
ew.a = weights
g.ep['edge_weight'] = ew
This should be a comment to Tiago's answer, but I don't have enough reputation for that.
For the latest version (2.26) of graph_tool I believe there is a missing transpose there. The i,j entry of the adjacency matrix denotes the weight of the edge going from vertex j to vertex i, so it should be
g.add_edge_list(transpose(transpose(adj).nonzero()))
import numpy as np
import graph_tool.all as gt
g = gt.Graph(directed=False)
adj = np.tril(adj)
g.add_edge_list(np.transpose(adj.nonzero()))
Without np.tril the adjacency matrix will contain entries with 2s instead one 1s because every edge is counted twice. Things like gt.num_edges() will be incorrect too.

Categories