2

I would like to plot a supply network structure. I have tried to use igraph, but until now did not come up with a reasonable result. An example would look like this:

library(igraph)
d <- read.table(text = "V1 V2 weight
            s1  p1  88
            s3  p1  100
            s2  p2  100
            s3  p2  43
            p1  c1  21
            p1  c2  79
            p1  c3  88
            p2  c1  22
            p2  c2  121
            ", stringsAsFactors = F, header = T)

g <- graph_from_data_frame(d, directed = T)
plot(g, layout=layout.fruchterman.reingold,
     edge.width=E(g)$weight/20,
     vertex.shape = "none", vertex.label.font = 2,
     vertex.label.cex=1.1, edge.color="gray70")   

Which gives:

enter image description here

The problem is that the network has an additional structure. A resonable - among others - result would show the "s"-nodes (for suppliers) should be in the left third, the "p"-nodes (plants) should be in the middle and the c-nodes (customers) on the right hand side. Is this even doable with igraph (and how)? Is there another package that could do this?

r.user.05apr
  • 5,356
  • 3
  • 22
  • 39
  • 1
    I _think_ you are describing a tripartite graph. See e.g. [Visualizing graph/network with 3 layeres (tripartite) in R/igraph](https://stackoverflow.com/questions/28974206/visualizing-graph-network-with-3-layeres-tripartite-in-r-igraph); [how to built tripartite network using .csv file in dataframe?](https://stackoverflow.com/questions/41319751/how-to-built-tripartite-network-using-csv-file-in-dataframe), [R is not taking the parameter hgap in layout_with_sugiyama](https://stackoverflow.com/questions/51194653/r-is-not-taking-the-parameter-hgap-in-layout-with-sugiyama). – Henrik Nov 14 '18 at 13:39

1 Answers1

2

Yes, this is doable with igraph. One way to make your own layout. A simple way to do this is to place all "s" nodes at x=1, "p" nodes at x=2 and "c" nodes at x=3. Each distinct node of each type (s,p,c) should get a unique y value so that they do not overlap. Using your example graph:

LO = matrix(0, nrow=vcount(g), ncol=2)
LO[grep("s", V(g)$name), 1] = 1
LO[grep("p", V(g)$name), 1] = 2
LO[grep("c", V(g)$name), 1] = 3
LO[,2] = ave(rep(1, vcount(g)), LO[,1], FUN = seq_along) 

plot(g, layout=LO, edge.width=E(g)$weight/20, 
     vertex.shape = "none", vertex.label.font = 2,
     vertex.label.cex=1.1, edge.color="gray70") 

Tripartite Graph

Also, following up on the comment of @Henrik, you can use layout_with_sugiyama. You still need to define the (s,p,c)-layers. Also, sugiyama arranges the layers vertically. You need to swap the x and y coordinates to get a horizontal layout.

Layers = rep(0,vcount(g))
Layers[grep("s", V(g)$name)] = 3
Layers[grep("p", V(g)$name)] = 2
Layers[grep("c", V(g)$name)] = 1
LO2 = layout_with_sugiyama(g, layers=Layers)$layout
LO2 = LO2[,2:1]

plot(g, layout=LO2, edge.width=E(g)$weight/20, 
     vertex.shape = "none", vertex.label.font = 2,
     vertex.label.cex=1.1, edge.color="gray70") 

Sugiyama layout

G5W
  • 36,531
  • 10
  • 47
  • 80