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.
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?
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
# 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]])
L <- new.g(g, 7)
plot(L[[1]], layout = L[[2]])