Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to control the igraph plot layout with Fixed Positions?

Tags:

r

igraph

I am trying to draw a network visualization to resemble a flow diagram. I'm fairly close with the following code, but I have a couple questions:

  1. Is this the best layout() algorithm, or can I manually assign a position for each node>
  2. How can I make sure that these nodes don't overlap in the plot (as they do here)?
  3. Can I assign one node as an "anchor" or starting point? i.e., can I make "C" the top-most or left-most node?

Thanks so much!!

library("igraph")
L3 <- LETTERS[1:8]
d <- data.frame(start = sample(L3, 16, replace = T), end = sample(L3, 16, replace = T),
                weight = c(20,40,20,30,50,60,20,30,20,40,20,30,50,60,20,30))


g <- graph.data.frame(d, directed = T)

V(g)$name 
E(g)$weight

ideg <- degree(g, mode = "in", loops = F)

col=rainbow(12) # For edge colors

plot.igraph(g, 
  vertex.label = V(g)$name, vertex.label.color = "gray20",
  vertex.size = ideg*25 + 40, vertex.size2 = 30,
  vertex.color = "gray90", vertex.frame.color = "gray20",
  vertex.shape = "rectangle",
  edge.arrow.size=0.5, edge.color=col, edge.width = E(g)$weight / 10,
  edge.curved = T, 
  layout = layout.reingold.tilford)
like image 490
david h Avatar asked Mar 19 '11 19:03

david h


2 Answers

The layout in igraph is defined in a matrix with 2 columns and a row for each node. The first column indicates its x position and the second its y position, and scale is not relevant (it is always rescaled to fit a -1 to 1 plotting area. You can get this layout before plotting by just calling the layout function on the graph:

 l <-layout.reingold.tilford(g) 
 l
     [,1] [,2]
[1,]    0    0
[2,]   -1    3
[3,]    0    1
[4,]    0    3
[5,]    0    2
[6,]    0    4
[7,]    1    3

This way you can change it in any way you want manually, and then send it to the plot:

plot.igraph(g, 
  vertex.label = V(g)$name, vertex.label.color = "gray20",
  vertex.size = ideg*25 + 40, vertex.size2 = 30,
  vertex.color = "gray90", vertex.frame.color = "gray20",
  vertex.shape = "rectangle",
  edge.arrow.size=0.5, edge.color=col, edge.width = E(g)$weight / 10,
  edge.curved = T, 
  layout = l)

It also seems that you can set the argument params to control the layout abit. This is a list containing an argument root that apparently can be used to set the root of the graph. Assign this a number of the node (renember that igraph uses C like indexes for nodes, first one is 0). So setting the root at "C":

l <- layout.reingold.tilford(g,params=list(root=2))

EDIT: Also the RGraphViz has some nice tree-layouts in it that might be worth checking out.


EDIT 2:

This is a modified snippet of the source codes from my package, which uses a same kind of layout matrix to define placement of nodes in a graph, that you might find useful:

gridLayout <- function(x)
{
    LmatX <- seq(-1,1,length=ncol(x))
    LmatY <- seq(1,-1,length=nrow(x))

    loc <- t(sapply(1:max(x),function(y)which(x==y,arr.ind=T)))
    layout <- cbind(LmatX[loc[,2]],LmatY[loc[,1]])
    return(layout)
}

What this function does is transform a matrix specifying the layout in a grid (similar to layout()) to a two-column layout with x and y positions. Define a matrix of zeros and for each node integer from 1 to the total number of nodes ( this is the igraph ID + 1 ).

For example, for a silly 4 node graph:

grid <- matrix(c(
    0,0,1,0,0,
    2,0,3,0,4),nrow=2,byrow=TRUE)

library("igraph")

g <- graph.adjacency(matrix(1,4,4))

plot(g,layout=gridLayout(L))
like image 196
Sacha Epskamp Avatar answered Nov 14 '22 06:11

Sacha Epskamp


A less complicated method than the above if you want to assign the node locations yourself is to add columns labelled x and y in your datasheet with the x and y coordinates for the respective nodes in those columns. e.g.

library('igraph')
nodes <- c('a','b','c','d')
x <- c(0,1,2,3)
y <- c(0,1,2,3)
from <- c('a','b','c')
to <- c('b','c','d')
NodeList <- data.frame(nodes, x ,y)
EdgeList <- data.frame(from, to)
a<- graph_from_data_frame(vertices = NodeList, d= EdgeList, directed = FALSE)
plot(a)

enter image description here

like image 43
unknown Avatar answered Nov 14 '22 07:11

unknown