rggplot2igraphggraphpatchwork

R how to properly scale patched network charts with edge loops


When working with network charts certain nodes may have edge loops, i.e., they are connected to themselves. When having multiple charts that are patched together where some nodes have edge loops, the charts get squeezed to some extent. Example 2 seems to work as expected but this is no longer the case in example 3 once there are multiple charts. Is there a cleaner way to achieve a nice patch between these charts such that all of them have the same size without some nodes being squeezed?

Example1: This unwanted behavior can be observed here, where in the right chart the nodes get clearly squeezed.

ex1

Example 2: When one changes from theme(aspect.ratio = 1) to coord_equal(), it seems to work for 2 charts (at least for the nodes but the size seems to be different).

ex2

Example 3: Once there are multiple charts (also using coord_equal()), the same charts get apparently scaled differently (e.g., charts 5 and 6). Alternatively using theme(aspect.ratio = 1) gets the size issue right but then again squeezes the respective nodes.

ex3

library(ggraph)
library(igraph)
library(patchwork)

set.seed(1)
adj_mat <- matrix(runif(100, 0, 10), nrow=10)
colnames(adj_mat) <- letters[10:1]
diag(adj_mat) <- 0

# create graph object and plot
g <- graph_from_adjacency_matrix(adj_mat, weighted = T, diag = T)
gg1 <- ggraph(g, layout = "circle") +
  geom_edge_link() +
  geom_edge_loop() +
  geom_node_circle(aes(r=0.15), fill = "orange") +
  geom_node_text(aes(label = colnames(adj_mat))) +
  #coord_equal()
  theme(aspect.ratio = 1)

# include edge loop
adj_mat[1, 1] = 5
g <- graph_from_adjacency_matrix(adj_mat, weighted = T, diag = T)
gg2 <- ggraph(g, layout = "circle") +
  geom_edge_link() +
  geom_edge_loop() +
  geom_node_circle(aes(r=0.15), fill = "orange") +
  geom_node_text(aes(label = colnames(adj_mat))) +
  #coord_equal()
  theme(aspect.ratio = 1)

# patch charts together
gg1 + gg2 # patch for examples 1 and 2
gg1 + gg1 + gg2 + gg1 + gg2 + gg2 # patch for example 3

Solution

  • The secret is to define fixed ranges on coord_equal. We don't often think about it when drawing netword graphs, but the nodes and edges are drawn on a ggplot with an x axis scale and y axis scale that are hidden at draw time. If we find out their dimensions, we can simply fix at a large enough value to safely draw all our plot elements:

    ce <- coord_equal(xlim = c(-1.4, 1.4), ylim = c(-1.4, 1.4))
    
    gg1 <- gg1 + ce
    gg2 <- gg2 + ce
    

    Now we have

    gg1 + gg2 
    

    enter image description here

    and

    gg1 + gg1 + gg2 + gg1 + gg2 + gg2 
    

    enter image description here