I am trying to plot a dendritic network (a river network) in R, using the ggnet2 function, and I want the y axis on the plot to be meaningful... specifically I want it to represent the basin area. I am looking for a method, then, that will calculate x coordinates so that the network displays nicely, with no crossing lines. How might I do this? See the code and example images below. In the first image, the y coordinates are specified to equal the area, which is what I want, but the x-coordinates are non-optimized so the graph looks ugly. In the second image, Fruchterman-Rhinegold placement looks great but the y coordinates are obviously arbitrary. I'm not wedded to using ggnet2, but I do want the network links to be angular (e.g. not like a clustering dendrogram with vertical links between nodes). Thanks!
[![library(GGally)
library(network)
library(sna)
graphmatrix <- matrix(c(0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), nrow=33)
sitenumbers <- c(26,27,30,3,31,6,4,18,32,5,11,21,29,16,8,7,14,25,13,19,23,9,15,12,17,20,28,10,1,2,24,22,33)
areas <- c(4.2,4.2,4.5,2.2,4.8,2.5,2.4,3.6,5.3,2.5,3.1,3.7,4.4,3.4,2.8,2.7,3.3,4.2,3.3,3.6,3.9,3.1,3.4,3.1,3.5,3.7,4.3,3.1,1,1.6,4.1,3.7,5.7)
wsnet <- network(graphmatrix, directed=TRUE)
layout <- gplot.layout.fruchtermanreingold(wsnet, NULL)
wsnet %v% 'sitenumber' = sitenumbers
wsnet %v% 'area' = areas
wsnet %v% 'randomnumber'= sample(sitenumbers)
ggnet2(wsnet, label='sitenumber')
#You can specify y coordinates, but then you need to also specify x coords, so there's tons of line crossing... I want to "optimize" the x coords.
ggnet2(wsnet, label='sitenumber', mode=c('randomnumber','area'))][1]][1]
Here would be a ggraph
solution to the problem. We'll start out by laying out a dendrogram and then tell ggraph to use the area as y positions.
library(tidygraph)
library(ggraph)
gr <- as_tbl_graph(wsnet)
lay <- create_layout(gr, "dendrogram")
lay$y <- lay$area
ggraph(lay) +
geom_edge_link() +
geom_node_point(size = 10, shape = 21, fill = "white") +
geom_node_text(aes(label = sitenumber))
Now obviously this is not perfect with intersecting lines and such, but it's a good starting point. You could tweak some positions manually:
lay$x[lay$sitenumber %in% c(12, 10, 17, 20, 28)] <- lay$x[lay$sitenumber %in% c(12, 10, 17, 20, 28)] + 1
lay$x[lay$sitenumber %in% c(1, 2)] <- lay$x[lay$sitenumber %in% c(1, 2)] - 2
lay$x[lay$sitenumber == 27] <- lay$x[lay$sitenumber == 27] + 2
lay$x[lay$sitenumber == 26] <- lay$x[lay$sitenumber == 26] + 3
ggraph(lay) +
geom_edge_link() +
geom_node_point(size = 10, shape = 21, fill = "white") +
geom_node_text(aes(label = sitenumber))
Adjust flavours to taste.