3
votes

I have the following dataframe:

df<-data.frame(consumed= c("level1_plt1", "level1_plt2", "level1_plt3", "level1_plt3","level1_plt2","level1_plt4","level1_plt5","level1_plt5","level1_plt6","level1_plt7","level1_plt8","level1_plt9","level1_plt10","level1_plt10","level1_plt1","level1_plt1","level1_plt6","level1_plt6","level1_plt9","level1_plt9","level1_plt11","level1_plt11","level1_plt11","level2_lep1","level2_lep4","level2_lep3"),consumer=c("level2_lep1","level2_lep2","level2_lep3","level2_lep2","level2_lep4", "level2_lep4","level2_lep5","level2_lep5","level2_lep6","level2_lep7","level2_lep8","level2_lep9","level2_lep10","level2_lep10","level2_lep8","level2_lep8","level2_lep1","level2_lep1","level2_lep3","level2_lep11","level2_lep12","level2_lep13","level2_lep13", "level3_pst1","level3_pst3","level3_pst4"))

And have preformed the following steps to get an igraph tripartite output:

links<- 
df%>%
group_by(consumed, consumer) %>% 
summarize(freq=n())

g<- graph_from_data_frame(d=links,directed=FALSE)

layer <- rep(2, length(V(g)$name))
layer[grepl("level1_",V(g)$name)]=1
layer[grepl("level3_",V(g)$name)]=3


names<- V(g)$name
names<-sub("level2_","", names)
names<-sub("level3_","", names)
names<-sub("level1_","", names)
V(g)$name = names


layout = layout_with_sugiyama(g, layers=layer)
E(g)$width <- E(g)$freq
V(g)$vertex_degree <-  degree(g)*7
plot(g,
 layout=cbind(layer,layout$layout[,1]),edge.curved=0,
 vertex.shape=c("square","circle","square")[layer],
 vertex.frame.color = c("darkolivegreen","darkgoldenrod","orange3")
[layer],
 vertex.color=c("olivedrab","goldenrod1","orange1")[layer],
 vertex.label.color="white",
 vertex.label.font=2,
 vertex.size=V(g)$vertex_degree,
 vertex.label.dist=c(0,0,0)[layer],
 vertex.label.degree=0, vertex.label.cex=0.5)

enter image description here

And I would like to do two things to adjust the picture, if possible:

  1. Order the layers from the largest shape (highest degree) to smallest shape (smallest degree). For example, in the green layer the order could be as follows: plt9, plt3,plt2,plt11,plt6,plt1,plt7,plt5,plt4,plt10,plt8.

  2. Create space between the shapes so that there is no overlap (e.g. lep3 and lep4). I like the current sizes/proportions so I am opposed to making shapes smaller to create space between shapes.

  3. Flip the graph and vertex font 90 degrees counter-clockwise so that from bottom to top it would be in the order green layer-->yellow layer-->orange layer. (I guess it is always an option to rotate vertex text and I can rotate the image in word or ppt.)

1

1 Answers

2
votes

I know this question is old, but I hope that the answer will help someone.

Rather than using layout_with_sugiyama, It may be easiest to do this with a custom layout. It is not very hard to do so. You already constructed the horizontal position with your layer variable. To get the vertical positions, we need to order the vertices by size (vertex_degree) and then allow shape proportional to the size, so we will set the height using cumsum on the vertex_degrees within each layer. After I make the layout the complex call to plot is the same as yours except that I swap my custom layout for your call to sugiyama.

MyLO = matrix(0, nrow=vcount(g), ncol=2)

## Horizontal position is determined by layer
MyLO[,1] = layer

## Vertical position is determined by sum of sorted vertex_degree
for(i in 1:3) {
    L  = which(layer ==i)
    OL = order(V(g)$vertex_degree[L], decreasing=TRUE)
    MyLO[L[OL],2] = cumsum(V(g)$vertex_degree[L][OL])
}

plot(g, 
 layout=MyLO,  edge.curved=0,
 vertex.shape=c("square","circle","square")[layer],
 vertex.frame.color = c("darkolivegreen","darkgoldenrod","orange3")[layer],
 vertex.color=c("olivedrab","goldenrod1","orange1")[layer],
 vertex.label.color="white",
 vertex.label.font=2,
 vertex.size=V(g)$vertex_degree,
 vertex.label.dist=0,
 vertex.label.degree=0, vertex.label.cex=0.5)

plot with layers ordered by vertex degree