Search code examples
graphigraphbipartitesna

Proportional link or node size in graph for R?


is there a way to draw the links or nodes of a network in igraph for R proportional to a minimum and maximum values?

Using link and node attributes for drawing is very handy in igraph, but in some networks the difference between the minimum and maximum values found in a network lead to a very ugly drawing. For instance, see this code:

#Transforming a sample network (Safariland) from the package bipartite into an igraph object
mat = Safariland
mat2 = cbind.data.frame(reference=row.names(mat),mat)
list = melt(mat2, na.rm = T)
colnames(list) = c("plant","animal","weight")
list[,1] = as.character(paste(list[,1]))
list[,2] = as.character(paste(list[,2]))
list2 = subset(list, weight > 0)
g = graph.data.frame(list2)
g2 = as.undirected(g)

#Plotting the igraph object with edge widths proportional to link weights
plot(g2,
 edge.width = E(g2)$weight)

The result is an odd-looking network, as the difference between link weights it too large. How can I draw those edges within a min-max range, so the network looks better?

Thank you very much.


Solution

  • You can apply any math or function to the values before passing them to the plot function. What you want is for example a rescaling function to map values to a different range as in this stackoverflow answer:

    mapToRange<-function(x,from,to){
        return(  (x - min(x)) / max(x - min(x)) * (to - from) + from)
    } 
    

    make example graph with random weights that are bad as line widths:

    library(igraph)
    g<-erdos.renyi.game(20,0.5)
    E(g)$weight<-runif(length(E(g)))^3 *100
    

    bad plot:

    plot(g, edge.width = E(g)$weight)
    

    better plot, rescaling the edge weights to values between 1 and 10 first with above function:

    weightsRescaled<-mapToRange(E(g)$weight,1,10)
    plot(g, edge.width = weightsRescaled)
    

    same thing more concise:

    plot(g, edge.width = mapToRange(E(g)$weight,1,10))