rfacetggraph

R ggraph facets


I'm having difficulty figuring out how to facet a graph properly.

See for example the following.

library(tidyverse)
library(tidygraph)
library(ggraph)

myedges <- data.frame(from=rep(letters[1:5],2),
                      to=c(rep(LETTERS[12:13],2),
                      rep(LETTERS[14],3),
                      LETTERS[15:16], 
                      LETTERS[17]),
                      n_user=sample(1:20, 10, replace=TRUE),
                      f=rep(c("face_A", "face_B"),5)
                      ) 


mynodes <- myedges %>% 
  pivot_longer(cols = c(from, to),
               names_to = "od",
               values_to = "node_name") %>% 
  group_by(node_name) %>% 
  summarise(n_user=sum(n_user)) 


g<-tbl_graph(nodes = mynodes, edges= myedges)

# Arc diagram with edge faceting, it seems ok but the nodes
ggraph(g, layout = 'linear') + 
  geom_edge_arc(aes(edge_width=n_user, label=n_user), label_pos=0.1, edge_alpha=0.2)+
  geom_node_point(aes(size=n_user), alpha=0.5, show.legend = FALSE)+
  geom_node_text(aes(label = node_name), size=3, nudge_y = - 0.5)+
  facet_edges(facets = vars(f), scales = "free")

The graph is almost fine except that I would like to have for each panel just the nodes that are effectively connected by edges: i.e. not having "orphan" nodes like the node "O" in the panel "face_A" or the node "P" in the panel "face_B".

Given that, I expect facet_nodes would be my potential solution by drawing just the nodes mapped by a variable and the corresponding edges for the nodes present in that panel.

I expect to accomplish that I need to introduce the mapping variable in nodes but here comes the problem because I can not conceive a proper way to do that.

The expected result is a graph with each panel node connected by edges

Any suggestions for that?


Solution

  • I think the problem here is that you are trying to plot two subgraphs using facets, but the nodes are not mutually exclusive across the faceting variable. This means you can't use facet_node. Since you are faceting by an edge attribute, you need to use facet_edge, but unfortunately facet_edge plots all the nodes, with no option to remove isolated nodes.

    The obvious way to get round this (even though it's a bit laborious) is to plot two different subgraphs and join them with patchwork:

    library(patchwork)
    
    gA <- g %>% 
      activate(edges) %>% 
      filter(f == "face_A") %>% 
      activate(nodes) %>% 
      filter(!node_is_isolated())
    
    gB <- g %>% 
      activate(edges) %>% 
      filter(f == "face_B") %>% 
      activate(nodes) %>% 
      filter(!node_is_isolated())
    
    p1 <- ggraph(gA, layout = 'linear') + 
      geom_edge_arc(aes(edge_width = n_user, label = n_user), 
                    label_pos = 0.1, edge_alpha = 0.2) +
      geom_node_point(aes(size=n_user), alpha = 0.5, show.legend = FALSE) +
      geom_node_text(aes(label = node_name), size = 3, nudge_y = - 0.5)  +
      facet_grid(.~f) +
      theme(legend.position = "none")
    
    p2 <- ggraph(gB, layout = 'linear') + 
      geom_edge_arc(aes(edge_width = n_user, label = n_user), 
                    label_pos = 0.1, edge_alpha = 0.2) +
      geom_node_point(aes(size = n_user), alpha = 0.5, show.legend = FALSE) +
      geom_node_text(aes(label = node_name), size = 3, nudge_y = - 0.5) +
      facet_grid(.~f)
    
    p1 + p2
    

    enter image description here