I'm trying to use the igraph
package to draw a (sparse) weighted graph. I currently have an adjacency matrix, but cannot get the graph.adjacency
function to recognise the edge weights.
Consider the following random symmetric matrix:
m <- read.table(row.names=1, header=TRUE, text=
" A B C D E F
A 0.00000000 0.0000000 0.0000000 0.0000000 0.05119703 1.3431599
B 0.00000000 0.0000000 -0.6088082 0.4016954 0.00000000 0.6132168
C 0.00000000 -0.6088082 0.0000000 0.0000000 -0.63295415 0.0000000
D 0.00000000 0.4016954 0.0000000 0.0000000 -0.29831267 0.0000000
E 0.05119703 0.0000000 -0.6329541 -0.2983127 0.00000000 0.1562458
F 1.34315990 0.6132168 0.0000000 0.0000000 0.15624584 0.0000000")
m <- as.matrix(m)
To plot, first I must get this adjacency matrix into the proper igraph
format. This should be relatively simple with graph.adjacency
. According to my reading of the documentation for graph.adjacency
, I should do the following:
library(igraph)
ig <- graph.adjacency(m, mode="undirected", weighted=TRUE)
However, it doesn't recognise the edge weights:
str(ig)
# IGRAPH UNW- 6 8 --
# + attr: name (v/c), weight (e/n)
# + edges (vertex names):
# [1] A--E A--F B--C B--D B--F C--E D--E E--F
plot(ig)
How do I get igraph to recognise the edge weights?
To get the weight of a particular edge from node x to y, simply take AdjacencyMatrix[x][y] . Either it'll be a weight, or INF indicating no link exists. At that point, summing the weight of a path is extremely simple.
WeightedAdjacencyMatrix returns a SparseArray object, which can be converted to an ordinary matrix using Normal. An entry wij of the weighted adjacency matrix is the weight of a directed edge from vertex νi to vertex νj. If there is no edge the weight is taken to be 0.
Adjacency matrix representationTo store weighted graph using adjacency matrix form, we call the matrix as cost matrix. Here each cell at position M[i, j] is holding the weight from edge i to j. If the edge is not present, then it will be infinity. For same node, it will be 0.
To fill the adjacency matrix, we look at the name of the vertex in row and column. If those vertices are connected by an edge or more, we count number of edges and put this number as matrix element. The matrix to represent a graph in this way is called Adjacency matrix .
The weights are there, weight (e/n)
means that there is an edge attribute called weight, and it is numeric. See ?print.igraph
. But they are not plotted by default, you need to add them as edge.label.
plot(ig, edge.label=round(E(ig)$weight, 3))
For plotting, make sure you read ?igraph.plotting
.
@TWL's solution can be easily generalized to represent edges' width as a function of the weights, including negative weights. The trick is to translate all weights by summing the value of the smallest weight (plus optionally an offset that represents the width of the minimum weight). For example:
# reproducible example:
set.seed(12345)
a <- matrix(runif(5*5, min=-10, max=10), ncol=5)
diag(a) <- 0 # remove loops.
>a
[,1] [,2] [,3] [,4] [,5]
[1,] 0.0000000 -6.6725643 -9.309291 -0.7501069 -0.9254385
[2,] 7.5154639 0.0000000 -6.952530 -2.2371204 -3.4649518
[3,] 5.2196466 0.1844867 0.000000 -1.9502972 9.3083065
[4,] 7.7224913 4.5541051 -9.977268 0.0000000 4.1496375
[5,] -0.8703808 9.7947388 -2.175933 9.0331751 0.0000000
# create igraph object.
g <- graph.adjacency(a, mode="undirected", weighted=TRUE)
plot(g)
# assign edge's width as a function of weights.
E(g)$width <- E(g)$weight + min(E(g)$weight) + 1 # offset=1
plot(g)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With