Search code examples
rgraphigraphnetwork-analysis

igraph: tree graph where terminal (not root) nodes are at same level?


I would like to plot a tree graph with igraph in R, having all the terminal nodes at the same level, unlike the default where all root nodes are at the same level.

layout_as_tree has a way to do this, based on the root nodes. One needs to specify them (root), as well as their level (rootlevel). So I could use this option, though it seem it would involve a very complicated workflow of a) splitting my tree into subtrees b) finding the root node of each subtree c) finding the largest path of each subtree 4) specifying root first level relative to others...

Is there a simpler way to do so by starting from the terminal nodes? Say I don't know which nodes are the root ones (1 and 11), but only know which ones are the terminal ones (4:11 and 16:20).

Here is an example, but I would like terminal nodes 4, 16 and 17 to be at the lowest level:

library(igraph)
tree2 <- make_tree(10, 3) + make_tree(10, 2)

plot(tree2, layout=layout_as_tree(tree2, root=c(1,11),
                                  rootlevel=c(2, 1)))

Created on 2022-09-23 with reprex v2.0.2


Solution

  • When counting the level from bottom to top, the solution becomes:

    require(igraph)
    
    tree2  <- make_tree(10, 3) + make_tree(10, 2) + edge(1,5)
    tree3  <- set_edge_attr(tree2, name="weight", value=-1) # longest path = shortest negative.
    dist   <- (-distances(tree3, v=(V(tree3)), mode="out")) # matrix of VxV distances of shortest paths.
    layers <- apply(dist, 1, max)                           # maximum distance from bottom to top (max per row).
    layers <- max(layers) - layers                          # minimal distance from top    to bottom.
    
    plot(tree3, layout=layout_with_sugiyama(tree3, layers=layers))
    

    If the dist matrix does not fit in memory then a dfs() search must be done, calculating the layers.