Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

igraph: positioning labels and removing empty space in grid layout

I want to make a function which plots directed graphs with vertices aligned and adds some text below each vertex, i.e. something like the example plot below. The plotting function should be able to handle pie graphs as vertices, so I have used igraph package in R.

adjm <- matrix(c(0,1,0,1,
                 0,0,1,1,
                 0,0,0,1,
                 0,0,0,0), nrow=4, byrow=TRUE)

g1 <- graph.adjacency(adjm, mode="directed")

values <- lapply(1:4, function(x) sample(1:4,4))

windows(width=7, height=3.5)

plot(g1, layout=layout.grid(g1, width=4), 
     vertex.shape="pie", vertex.pie=values,
     vertex.pie.color=list(heat.colors(4)),
     edge.curved=TRUE,
     vertex.label=LETTERS[1:4], vertex.size=50,
     vertex.label.dist=5, vertex.label.degree=pi/2, 
     edge.label=1:5, rescale=FALSE, 
     xlim=c(-0.2,3.5), ylim=c(0,0.5))

enter image description here

I have two problems.

  1. Why is it that the longer the vertex label, the longer the distance to the vertex centre as in the following example? Can I force them to appear at the same level without manually finding and defining them the right distance?

    windows(width=7, height=3.5)
    
    plot(g1, layout=layout.grid(g1, width=4), 
         vertex.shape="pie", vertex.pie=values,
         vertex.pie.color=list(heat.colors(4)),
         edge.curved=TRUE,
         vertex.label=c("A", "AA", "AAAA", "AAAAAA"), vertex.size=50,
         vertex.label.dist=5, vertex.label.degree=pi/2, 
         edge.label=1:5, rescale=FALSE, 
         xlim=c(-0.2,3.5), ylim=c(0,0.5))
    

    enter image description here

  2. How to remove empty space when plotting aligned plots? If I make a horizontal graph it will be placed at the bottom of the window with a lot of empty space. The flatter the image, the smaller the graph, as in the third plot. (It seems that the size of the graph is determined such that the plot would fit in any position, vertical or horizontal.)

    plot(g1, layout=layout.grid(g1, width=4), 
         vertex.shape="pie", vertex.pie=values,
         vertex.pie.color=list(heat.colors(4)),
         edge.curved=TRUE,
         vertex.label=c("A", "AA", "AAAA", "AAAAAA"), vertex.size=20,
         vertex.label.dist=2, vertex.label.degree=pi/2, edge.label=1:5)
    

    enter image description here I can write argument asp=0 to keep the vertices the right size in a flatter window but the automatic curvatures and the positions of the vertex labels change. I can manually tweak negative upper margin, label distances, and edge curvature, but of course this is not a solution for a generic function. The best result so far was the result of rescale=FALSE as in the code for the first plot, but the edge curvatures are still too small and with larger vertices they get behind the vertices completely. (Also, the problem with varying vertex label distances still remains.) Direct use of autocurve.edges is not giving me any curvature. Any ideas of what to try next?

like image 338
Satu Avatar asked Feb 16 '15 13:02

Satu


1 Answers

To fix this, you might want to tweak the plot.igraph function a little bit. To do this, you can experiment using trace(plot.igraph,edit=TRUE) and modify the code of the function.

A few tips to get what you want: For the labels, line 319 of the function is:

y <- layout[, 2] + label.dist * sin(-label.degree) * (vertex.size + 6 * 8 * log10(nchar(labels) + 1))/200

So the y placement of the labels is proportional to the number of characters of the label, just remove the log10(nchar(labels) + 1) and the labels will stay at the same level.

For the size issue, if you want to keep rescale, the y position of the plot is defined line 55

layout <- layout.norm(layout, -1, 1, -1, 1)

You can change the third number to whatever you want and the plot will be higher (for example, layout <- layout.norm(layout, -1, 1, 0, 1) will center the vertexes on 0). You can also change the margins by changing thepar` settings. You could for example do:

oldMargins<-par("mar")
par(mar=c(10,4,4,4))

and after the plot par(mar=oldMargins)

This is the plot I get using this code after the adjustments:

enter image description here

I left the axes to make it easier to tweak, and removed the pies because no value was given in your post.

oldMargins<-par("mar")
par(mar=c(10,4,4,4))
plot(g1, layout=layout.grid(g1, width=4),
     vertex.pie.color=list(heat.colors(4)),
     edge.curved=TRUE,
     vertex.label=c("A", "AA", "AAAA", "AAAAAA"), vertex.size=20,
     vertex.label.dist=1, vertex.label.degree=pi/2, edge.label=1:5,axes=TRUE,
     ylim=c(-0.5,0.5),xlim=c(-1,1))
par(mar=oldMargins)

When you restart R, any changes you made to the function will be removed, or you can use untrace to go back to the original function. You can look at this post for more info.

like image 114
NicE Avatar answered Sep 24 '22 22:09

NicE