rpositionigraphggraph

How to fix position of nodes in ggraph to generate various networks?


I can't create networks with fixed node positions that can vary from one network to another.

I have to generate various graphs with a key node in the central position then the other nodes all around. I want to be able to compare them to each other. So I thought to put all the nodes even the central one all around (to keep the same order) but in gray (or with opacity) when it is this network that I observe, as well as the nodes not intervening in this network (figure C and D).

I did a minimal and reproducible example. With my table of links and then a graph for the group Group1 and another for the Group7. With my code I manage to generate the graphs in figure A and B.

enter image description here

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

set.seed(1234)

links_all = tibble::tribble(
  ~x,  ~input,    ~output,   ~direction,  ~weight,  
  2,   "Group3",  "Group4",  "positive",  0.55076, 
  3,   "Group3",  "Group5",  "positive",  0.25263, 
  4,   "Group3",  "Group7",  "positive",  0.14137, 
  5,   "Group3",  "Group8",  "positive",  0.1532,  
  6,   "Group3",  "Group6",  "positive",  0.51479, 
  7,   "Group3",  "Group9",  "positive",  0.2315,  
  8,   "Group3",  "Group1",  "positive",  0.21106, 
  9,   "Group3",  "Group2",  "negative",  0.51237, 
  12,  "Group4",  "Group5",  "positive",  0.14874, 
  13,  "Group4",  "Group7",  "positive",  0.16683, 
  14,  "Group4",  "Group8",  "positive",  0.235,   
  15,  "Group4",  "Group6",  "positive",  0.43237, 
  16,  "Group4",  "Group9",  "positive",  0.30848, 
  17,  "Group4",  "Group1",  "positive",  0.0544,  
  18,  "Group4",  "Group2",  "negative",  0.48404, 
  22,  "Group5",  "Group7",  "positive",  0.22572, 
  24,  "Group5",  "Group6",  "positive",  0.1611,  
  25,  "Group5",  "Group9",  "positive",  0.09827, 
  26,  "Group5",  "Group1",  "positive",  0.15555, 
  27,  "Group5",  "Group2",  "negative",  0.27293, 
  32,  "Group7",  "Group8",  "positive",  0.0736,  
  33,  "Group7",  "Group6",  "positive",  0.12604, 
  34,  "Group7",  "Group9",  "positive",  0.13935, 
  35,  "Group7",  "Group1",  "negative",  0.0994,  
  42,  "Group8",  "Group6",  "positive",  0.08693, 
  43,  "Group8",  "Group9",  "positive",  0.23976, 
  44,  "Group8",  "Group1",  "negative",  0.42419, 
  45,  "Group8",  "Group2",  "negative",  0.27792, 
  52,  "Group6",  "Group9",  "positive",  0.1356,  
  53,  "Group6",  "Group1",  "positive",  0.14775, 
  54,  "Group6",  "Group2",  "negative",  0.33881, 
  62,  "Group9",  "Group1",  "negative",  0.07413, 
  63,  "Group9",  "Group2",  "negative",  0.2427,  
  72,  "Group1",  "Group2",  "negative",  0.56563
)

plot_graph = function(current_group, get_legend_taxa = FALSE) {
  print(current_group)
  #init var 
  links_all_current = NULL
  nodes_all = NULL
  graph = NULL
  col_phyla = NULL
  width_edge_all = NULL
  current_graph = NULL
  
  links_all_current = links_all %>%
    setNames(c("ids", "from", "to", "type", "weight")) %>%
    mutate(weight_class = as.character(round(weight,1))) %>%
    select(-ids) %>%
    filter(from == {{current_group}} | to == {{current_group}})
  
  nodes_all = links_all_current %>%
    rowid_to_column() %>%
    select(rowid, from, to) %>%
    pivot_longer(-rowid, values_to = "id") %>%
    distinct(id) %>%
    rowid_to_column() %>%
    relocate(rowid, .after = last_col())
  
  graph = tbl_graph(nodes = nodes_all, edges = links_all_current, directed = FALSE)
  graph
  
  # setting theme_graph 
  set_graph_style()
  
  width_edge_all = as.numeric(links_all_current$weight_class)*5
  names(width_edge_all) = as.numeric(links_all_current$weight_class)
  common_scale2_all = scale_edge_width_manual(values = width_edge_all)
  
  
  if (get_legend_taxa == TRUE){
    print("legend")
    # plot with legend
    current_graph = graph %>%
      ggraph(layout = 'focus',  focus = 1, circular = TRUE) + #
      geom_edge_arc(aes(color = type, width = weight_class)) +
      geom_node_point(aes(size = 2, colour = id)) +
      geom_node_label(aes(label = id),
                      size = 2,
                      # position = "identity",
                      parse = FALSE,
                      nudge_x = 0.1,
                      nudge_y = 0.1,
                      label.padding = unit(0.25, "lines"),
                      label.r = unit(0.15, "lines"),
                      label.size = 0.25,
                      family = "sans",
                      repel = F) +
      scale_edge_color_manual(values = c("negative" = "#ab0033",
                                         "positive" = "#009d4f")) +
      common_scale2_all
    current_graph
  } else {
    # basic plot
    current_graph = graph %>%
      ggraph(layout = 'focus',  focus = 1, circular = TRUE) + #
      geom_edge_arc(aes(color = type, width = weight_class)) +
      geom_node_point(aes(size = 2, colour = id)) +
      geom_node_label(aes(label = id),
                      size = 2,
                      # position = "identity",
                      parse = FALSE,
                      nudge_x = 0.1,
                      nudge_y = 0.1,
                      label.padding = unit(0.25, "lines"),
                      label.r = unit(0.15, "lines"),
                      label.size = 0.25,
                      family = "sans",
                      repel = F) +
      scale_edge_color_manual(values = c("negative" = "#ab0033",
                                         "positive" = "#009d4f")) +
      common_scale2_all
    current_graph
  }
}

Group1 = plot_graph("Group1", FALSE)
Group1

Group7 = plot_graph("Group7", FALSE)
Group7
)

Do you have any tips for coding this?


Solution

  • Not sure qbout the packcages you uses.. An igraph-solution could be:

    library(igraph)
    library(data.table)
    # create the graph
    nodes <- sort(unique(c(links_all$input, links_all$output)))
    myvert <- data.frame(name = nodes, id = 1:length(nodes))
    g <- graph_from_data_frame(links_all[2:3], vertices = myvert)
    plot(g, layout = layout.circle)
    

    looks like

    enter image description here

    # get initial coordinates
    base.coords <- as.data.table(cbind(myvert, layout.circle(g)))
    # function to create subgraph from g, center vertex with id vid
    new.g <- function(g, vid) {
      g2 <- subgraph.edges(g, E(g)[.inc(V(g)[id == vid])])
      new.coords <- as.matrix(base.coords[id %in% V(g2)$id, ][id == vid, `:=`(`1`= 0, `2` = 0)][, 3:4])
      return(list(g2, new.coords))
    }
    
    L <- new.g(g, 1)
    plot(L[[1]], layout = L[[2]]) 
    

    enter image description here

    L <- new.g(g, 7)
    plot(L[[1]], layout = L[[2]]) 
    

    enter image description here