A beginning section loads the necessary packages and defines the starting directory.

pacman::p_load(dplyr, networktools, ggplot2, BGGM,
               emojifont, fontawesome)

Load raw data

Data and models can be found on the Open Science Framework at https://osf.io/42ueg/. Rather than re-running models, we will load them here.

t1 <- read.csv(here::here("DATA", "t1.csv"))
t2 <- read.csv(here::here("DATA", "t2.csv"))

Load models

Load the pre-created {BGGM} models. (When running the code to replicate analyses, you may set models_loaded to false in the preamble at the top of this document if planning to knit, or run all chunks manually, if you would like to generate the models anew.)

load(here::here("DATA", "models", "C1.Rdata"))
load(here::here("DATA", "models", "C2.Rdata"))
load(here::here("DATA", "models", "C3.Rdata"))
load(here::here("DATA", "models", "E1.Rdata"))
load(here::here("DATA", "models", "E2.Rdata"))
load(here::here("DATA", "models", "E3.Rdata"))

Set some defaults

Source the make_adj_plot() function and the add_neg_edges() function

# load code for plot functions
# including modified functions originally 
# by Josue Rodriguez, as well as
# the helper function insertLayer() for adding layers
# to ggplots
source(here::here("R Syntax", "network_plots.R"))

# set colors
pal <- c("#1b9e77", "#d95f02", "#7570b3")
node_font_color <- "white"

Create data frames with network variables

end_network_activity_game <- t1 %>% 
  dplyr::select(end_phone:end_time, 
                home_exercise:work_outside_home)
end_network_activity_game$id <- NULL

end_network_dep <- t1 %>% 
  dplyr::select(end_phone:end_time, 
                PHQ.8_1:PHQ.8_8)
end_network_dep$id <- NULL

act_network_dep <- t1 %>% 
  dplyr::select(home_exercise:work_outside_home, 
                PHQ.8_1:PHQ.8_8)
act_network_dep$id <- NULL

Network 1: real-life and in-game activity

Create network in {BGGM}

Exploratory network

First, construct the activites & game network

if(! params$models_loaded) {
  set.seed(NULL) # needed for knitr to play well with BGGM
  explore_network1 <- BGGM::explore(end_network_activity_game,
                                  type = "mixed",
                                  iter = 5000,
                                  seed = 1)
  E1 <- BGGM::select(explore_network1,
                     alternative = "exhaustive",
                     bf_cut = 3)
}

Plot using the {BGGM} plotting:

# plot(E1, edge_magnify = 5, ci_width = 0.95)
if(pacman::p_isloaded("BGGM")) {
  allp <- plot(E1, edge_magnify = 5, ci_width = 0.95)
  gridExtra::grid.arrange(grobs = allp)
}

Retain positive partial correlations from the real-life/game variables. Define names for nodes and communities.

partial_cors_pos <- E1$pcor_mat * E1$pos_mat
partial_cors_neg <- E1$pcor_mat * E1$neg_mat

#vector for nodenames
node_names <- colnames(end_network_activity_game)
#node_names <- colnames(confirm_E1)
#create communities
comms <- c(rep("Game Activity", 9), rep("Real Activity", 21))
# rename columns with node names
dimnames(partial_cors_pos) <- list(node_names, node_names)
dimnames(partial_cors_neg) <- list(node_names, node_names)

Calculate bridge strength. comms is a vector specifying the community for each node. We will use the top 10% in bridge strength as bridge nodes.

bridge_strengths_pos <- networktools::bridge(partial_cors_pos, communities = comms)$`Bridge Strength`
bridge_strengths_neg <- networktools::bridge(partial_cors_neg, communities = comms)$`Bridge Strength`

# bridge nodes:
bridge_strength_cutoff <- quantile(bridge_strengths_pos, 0.9)
bridge_strengths_pos[bridge_strengths_pos > bridge_strength_cutoff]
##         end_phone         end_drink work_outside_home 
##             0.810             0.632             0.591
bridge_strength_cutoff2 <- quantile(bridge_strengths_neg, 0.9)
bridge_strengths_neg[bridge_strengths_neg > bridge_strength_cutoff2]
##    end_phone end_exercise         knit 
##        0.363        0.389        0.590

Confirmatory

Create the confirmatory network.

confirm_E1 <- t2 %>% 
  dplyr::select(end_phone:end_time, 
                home_exercise:work_outside_home)
confirm_E1$id <- NULL
if(! params$models_loaded) {
  confirm_network1 <- BGGM::explore(confirm_E1,
                                    type = "mixed",
                                    iter = 5000,
                                    seed = 1)
  C1 <- BGGM::select(confirm_network1, bf_cut = 3)
}

Plot using the BGGM base plotting:

if(pacman::p_isloaded("BGGM")) {
  allp_C1 <- plot(C1, edge_magnify = 5, ci_width = 0.95)
  gridExtra::grid.arrange(grobs = allp_C1)
}

Cleaned up plots for Network 1 (depression and in-game activity)

Note that some variations of the plot may cause some dashed lines to print with only minor spaces, and thus appear to be solid. They seem to work best when perfectly circular.

Exploratory plots

The first plot highlights the bridge nodes. First we’ll prepare the names, then plot it.

# we previously defined the node_names1:
# node_names1 <- colnames(end_network_activity_game)
# let's give them more descriptive names

node_names1 <- c("Gphone", "Gcomp", "Galco", "Gtv", "Gexer",
                 "Gcook", "GhobbN", "GhobbO", "Gtime",
                 "RexerH", "RexerO", "Rgym", "Rcook",
                 "Rvol", "Rtv", "Rvg", "Rknit", "Rread",
                 "RhobbN", "Ralco", "Rmj", "Rsubs", "Rreas",
                 "Rsmed", "Ryoga", "Rwrit", "Rmus", "Rzoom",
                 "Rwfh", "Roffic")
# provide descriptors
captions1 <- c("in-game phone use", "in-game time on computer",
               "in-game drinking alcohol", "in-game TV use",
               "in-game exercise", "in-game cooking",
               "in-game new hobby", "in-game old hobby",
               "time spent in-game", "real-life in-home exercise",
               "real-life outdoor exercise", "real-life gym",
               "real-life baking and cooking",
               "real-life volunteering",
               "real-life TV use", "real-life videogames",
               "real-life knitting", "real-life reading",
               "real-life new hobbies", "real-life drinking alcohol",
               "real-life marijuana use",
               "real-life substance use (other)",
               "real-life reassurance-seeking",
               "real-life social media use", "real-life yoga",
               "real-life writing", "real-life playing music",
               "real-life video calls with friends",
               "real-life working from homew",
               "real-life working outside the home")

# create key-value pairs for referencing:
captions1 <- tibble(captions1, node_names1)
equivalencies <- setNames(as.list(node_names1), colnames(end_network_activity_game))

# rename communities (especially for legend)
comms1 <- c(rep("Game Activity", 9), rep("Real Activity", 21))

# bridge names by direction:
posnames <- names(bridge_strengths_pos[bridge_strengths_pos > bridge_strength_cutoff])
negnames <- names(bridge_strengths_neg[bridge_strengths_neg > bridge_strength_cutoff2])
posnames <- equivalencies[posnames] %>% unlist()
negnames <- equivalencies[negnames] %>% unlist()

bridgenames <- c(posnames, negnames[! negnames %in% posnames])
fadenames <- node_names1[! node_names1 %in% bridgenames]

Plot using make_adj_plot() from sourced functions. Add on the negative layer using add_neg_edges() from same. A wrapping function create_net_plot() is sourced from the create_plot.R; it simply adds on themes to the make_adj_plot() function.

source(here::here("R syntax", "create_plot.R"))

plot_cd_E <- function(plot_node_size = node_size,
                      adj_limits = .1, fontsize = 15
                      ) {
  create_net_plot(plot_node_size = plot_node_size, 
                 within = FALSE,
                 adj_limits = adj_limits, 
                 adj_pos = E1$pos_mat, adj_neg = E1$neg_mat,
                 node_labels = node_names1, 
                 node_label_col = node_font_color,
                 communities = comms1,
                 bridges_pos = bridgenames, bridges_neg = negnames,
                 fade = fadenames,
                 model_parcors = E1$pcor_mat,
                 type = "cd", 
                 scale_labels = c("Game Endings",
                                 "Real-Life Activities"),
                 fontsize = fontsize,
                 fontawesome = FALSE)
}

# save the legend for use later
# legend_E1 <- add_legend(plot_cd_E())

plot_cd_E(fontsize = 7)

Print captions:

captions1 <- captions1 %>%
  rowwise() %>%
  mutate(combined = paste0(c(node_names1, captions1), collapse=": ")) %>%
  pull(combined)

cat(captions1, sep = "\n")
## Gphone: in-game phone use
## Gcomp: in-game time on computer
## Galco: in-game drinking alcohol
## Gtv: in-game TV use
## Gexer: in-game exercise
## Gcook: in-game cooking
## GhobbN: in-game new hobby
## GhobbO: in-game old hobby
## Gtime: time spent in-game
## RexerH: real-life in-home exercise
## RexerO: real-life outdoor exercise
## Rgym: real-life gym
## Rcook: real-life baking and cooking
## Rvol: real-life volunteering
## Rtv: real-life TV use
## Rvg: real-life videogames
## Rknit: real-life knitting
## Rread: real-life reading
## RhobbN: real-life new hobbies
## Ralco: real-life drinking alcohol
## Rmj: real-life marijuana use
## Rsubs: real-life substance use (other)
## Rreas: real-life reassurance-seeking
## Rsmed: real-life social media use
## Ryoga: real-life yoga
## Rwrit: real-life writing
## Rmus: real-life playing music
## Rzoom: real-life video calls with friends
## Rwfh: real-life working from homew
## Roffic: real-life working outside the home

With icons instead of names

We found an icon-based plot to be much more straightforward to read. The plot is created below; it should be identical to the above plot except with icons based on Font Awesome and using the {emojifont} package.

If you save your plot to a PDF, you may need to embed the fonts as well, using grDevices::embedFonts or extrafont::embed_fonts. However, the plot saves to png without issue.

load.fontawesome()

node_names1FAname <- c("fa-mobile", # game phone use
                "fa-laptop", # game computer
                "fa-beer", # game drinking
                "fa-tv", # game tv
                "fa-heartbeat", # game exercise
                "fa-cutlery", # cooking
                "fa-random", # new hobby
                "fa-object-group", # hobby old
                "fa-clock-o", # end game time
                "fa-bicycle", # home exercise
                "fa-futbol-o", # outside exercise
                "fa-hashtag", # gym
                "fa-cutlery", # cooking
                "fa-handshake-o", # volunteering
                "fa-tv", # tv
                "fa-gamepad", # videogames
                "fa-connectdevelop", # knitting
                "fa-book", # reading
                "fa-modx", # new hobbies
                "fa-glass", # alcohol
                "fa-leaf", # marijuana
                "fa-flask", # other substances fa-eye-slash?
                "fa-hand-peace-o", # reassurance
                "fa-twitter", # social media
                "fa-sun-o", # yoga   # refresh?
                "fa-pencil", # writing
                "fa-music", # music playing
                "fa-skype", # videocalls with friends
                "fa-window-restore", # working from home
                "fa-building-o" # working from the office
                 )
# convert to icons
node_names1FA <- fontawesome(node_names1FAname)

# provide descriptors
captions1FA <- c("in-game phone use", "in-game time on computer",
               "in-game drinking alcohol", "in-game TV use",
               "in-game exercise", "in-game cooking",
               "in-game new hobby", "in-game old hobby",
               "time spent in-game", "real-life in-home exercise",
               "real-life outdoor exercise", "real-life gym",
               "real-life baking and cooking",
               "real-life volunteering",
               "real-life TV use", "real-life videogames",
               "real-life knitting", "real-life reading",
               "real-life new hobbies",
               "real-life drinking alcohol",
               "real-life marijuana use",
               "real-life substance use (other)",
               "real-life reassurance-seeking",
               "real-life social media use", "real-life yoga",
               "real-life writing", "real-life playing music",
               "real-life video calls with friends",
               "real-life working from homew",
               "real-life working outside the home")
# create key-value pairs:
equivalenciesFA <- setNames(as.list(node_names1FA),
                            colnames(end_network_activity_game))
comms1 <- c(rep("Game Activity", 9), rep("Real Activity", 21))

# bridge names:
posnamesFA <- names(bridge_strengths_pos[bridge_strengths_pos > bridge_strength_cutoff])
negnamesFA <- names(bridge_strengths_neg[bridge_strengths_neg >
                                           bridge_strength_cutoff2])
posnamesFA <- equivalenciesFA[posnamesFA] %>% unlist()
negnamesFA <- equivalenciesFA[negnamesFA] %>% unlist()

bridgenamesFA <- c(posnamesFA, negnamesFA[! negnamesFA %in% posnamesFA])
fadenamesFA <- node_names1FA[! node_names1FA %in% bridgenamesFA]

Make the plot:

plot_cd_EFA <- function(plot_node_size = node_size,
                        adj_limits = .1, fontsize = 15
                        ) {
  create_net_plot(plot_node_size = plot_node_size, 
                 within = FALSE,
                 adj_limits = adj_limits, 
                 adj_pos = E1$pos_mat, adj_neg = E1$neg_mat,
                 node_labels = node_names1FA, 
                 node_label_col = node_font_color,
                 communities = comms1,
                 bridges_pos = bridgenamesFA, bridges_neg = negnamesFA,
                 fade = fadenamesFA,
                 model_parcors = E1$pcor_mat,
                 type = "cd", 
                 scale_labels = c("Game Endings",
                                 "Real-Life Activities"),
                 fontsize = fontsize,
                 fontawesome = TRUE)
}

plot_cd_EFA(fontsize = 12)

In game:

  • : phone use
  • : time on computer
  • : alcohol use
  • : TV use
  • : in-game exercise
  • : cooking
  • : new hobby
  • : old hobby
  • : time spent

Real-life:

  • : home exercise
  • : outdoor exercise
  • : gym
  • : cooking
  • : volunteering
  • : TV use
  • : videogames
  • : knitting
  • : reading
  • : new hobbies
  • : drinking alcohol
  • : marijuana use
  • : other substance use
  • : reassurance-seeking
  • : social media use
  • : yoga
  • : writing
  • : playing music
  • : video calls with friends
  • : working from home
  • : working outside the home

Community-independent plots (CI)

The second plot shows the community-independent plot (CI).

plot_ci_E <- function(plot_node_size = node_size,
                        adj_limits = .1, fontsize = 15
                        ) {
  create_net_plot(plot_node_size = plot_node_size, 
                 within = FALSE,
                 adj_limits = adj_limits, 
                 adj_pos = E1$pos_mat, adj_neg = E1$neg_mat,
                 node_labels = node_names1, 
                 node_label_col = node_font_color,
                 communities = comms1,
                 bridges_pos = NULL, bridges_neg = NULL,
                 fade = NULL,
                 model_parcors = E1$pcor_mat,
                 type = "ci", 
                 scale_labels = c("Game Endings",
                                 "Real-Life Activities"),
                 fontsize = fontsize,
                 fontawesome = FALSE)
}

plot_ci_E(fontsize = 7)

Confirmatory plots

The same bridge nodes are highlighted as in the exploratory network, regardless of whether those nodes are in fact bridge nodes in the confirmatory network.

Using a bit of code borrowed from BGGM::plot.select(), we adjusted the make_adj_plot() so that if we set confirmatory = TRUE, it will change edges to dashed if they have negative weights. This works with fontawesome = TRUE, as well.

plot_C1 <- C1$pcor_mat * C1$Adj_10 # instead of C1$pcor_mat_zero
plot_cd_C1 <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C1, 
                  node_labels = node_names1, 
                  node_label_col = node_font_color,
                  communities = comms1,
                  bridges_pos = bridgenames, 
                  fade = fadenames,
                  model_parcors = C1$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("Game Endings",
                                  "Real-Life Activities"),
                  fontsize = fontsize,
                  fontawesome = FALSE)
}

plot_cd_C1(fontsize = 7)

We can run this with the FontAwesome icons, too:

# plot_C1 <- C1$pcor_mat * C1$Adj_10 # instead of C1$pcor_mat_zero
plot_cd_C1_FA <- function(plot_node_size = node_size,
                          adj_limits = .1, fontsize = 15
                          ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C1, 
                  node_labels = node_names1FA, 
                  node_label_col = node_font_color,
                  communities = comms1,
                  bridges_pos = bridgenamesFA, 
                  fade = fadenamesFA,
                  model_parcors = C1$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("Game Endings",
                                   "Real-Life Activities"),
                  fontsize = fontsize,
                  fontawesome = TRUE)
}

plot_cd_C1_FA(fontsize = 12)

Within-community edges

The following plots don’t mask the within-community edges, by using the variant within = TRUE in the create_net_plot() function, and therefore include_within = TRUE to the make_adj_plot() function. This pairs with confirmatory = TRUE and also fontawesome = TRUE.

plot_cd_C1_FA_within_edges <- function(plot_node_size = node_size,
                          adj_limits = .1, fontsize = 15
                          ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = TRUE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C1, 
                  node_labels = node_names1FA, 
                  node_label_col = node_font_color,
                  communities = comms1,
                  bridges_pos = bridgenamesFA, 
                  fade = fadenamesFA,
                  model_parcors = C1$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("Game Endings",
                                   "Real-Life Activities"),
                  fontsize = fontsize,
                  fontawesome = TRUE)
}

plot_cd_C1_FA_within_edges(fontsize = 12)

Network 2: PHQ & In-game activities

Create network in {BGGM}

Exploratory network

if(! params$models_loaded) {
  set.seed(NULL) # needed for knitr to play well with BGGM
  explore_network2 <- BGGM::explore(end_network_dep,
                                    type = "continuous",
                                    iter = 5000,
                                    seed = 1)
  E2 <- BGGM::select(explore_network2,
                     alternative = "exhaustive",
                     bf_cut = 3)
}

if(pacman::p_isloaded("BGGM")) {
  allp2 <- plot(E2, edge_magnify = 5, ci_width = 0.95)
  gridExtra::grid.arrange(grobs = allp2)
}
# retain positive & negative partial correlations from the PHQ/game variables
partial_cors_pos2 <- E2$pcor_mat * E2$pos_mat
partial_cors_neg2 <- E2$pcor_mat * E2$neg_mat
#vector for nodenames
node_names2 <- colnames(end_network_dep)
node_names2 <- colnames(end_network_dep)
#create communities
comms2 <- c(rep("Game Activity", 9), rep("PHQ", 8))
# rename columns with node names
dimnames(partial_cors_pos2) <- list(node_names2, node_names2)
dimnames(partial_cors_neg2) <- list(node_names2, node_names2)

# calculate bridge strength. comms is a vector specifying
# the community for each node
bridge_strengths_pos2 <- networktools::bridge(partial_cors_pos2, communities = comms2)$`Bridge Strength`
bridge_strengths_neg2 <- networktools::bridge(partial_cors_neg2, communities = comms2)$`Bridge Strength`

# we use the top 10% in bridge strength as bridge nodes
bridge_strength_cutoff.b <- quantile(bridge_strengths_pos2, 0.9)
bridge_strengths_pos2[bridge_strengths_pos2 > bridge_strength_cutoff.b]
## end_cook  PHQ.8_1 
##    0.254    0.247
bridge_strength_cutoff2.b <- quantile(bridge_strengths_neg2, 0.9)
bridge_strengths_neg2[bridge_strengths_neg2 > bridge_strength_cutoff2.b]
## PHQ.8_2 PHQ.8_5 
##   0.245   0.275

Confirmatory

confirm_E2 <- t2 %>%
  dplyr::select(end_phone:end_time, PHQ.8_1:PHQ.8_8)
confirm_E2$id <- NULL

if(! params$models_loaded) {
  confirm_network2 <- BGGM::explore(confirm_E2,
                                  type = "continuous",
                                  iter = 5000,
                                  seed = 1)
  C2 <- BGGM::select(confirm_network2)
}

if(pacman::p_isloaded("BGGM")) {
  allC2 <- plot(C2, edge_magnify = 5, ci_width = 0.95)
  gridExtra::grid.arrange(grobs = allC2, ncol = 2)
}

Plots for Network 2 (PHQ & In-game activities)

Since these are smaller networks, node size can be larger. (Probably 33 for saving and 30 in-document.)

node_size <- node_size + 5 - ifelse(params$save_all_plots, 2, 0)

Exploratory plots

node_names2 <- c("Gphone", "Gcomp", "Galco", "Gtv", "Gexer",
                 "Gcook", "GhobbN", "GhobbO", "Gtime",
                 "PHQ-1", "PHQ-2", "PHQ-3", "PHQ-4",
                 "PHQ-5", "PHQ-6", "PHQ-7", "PHQ-8")
# provide descriptors
captions2 <- c("in-game phone use", "in-game time on computer",
               "in-game drinking alcohol", "in-game TV use",
               "in-game exercise", "in-game cooking",
               "in-game new hobby", "in-game old hobby",
               "time spent in-game", "PHQ-1: little interest",
               "PHQ-2: feeling down", "PHQ-3: sleep trouble",
               "PHQ-4: low energy", "PHQ-5: appetite",
               "PHQ-6: failure", "PHQ-7: concentration",
               "PHQ-8: psychomotor")
# create key-value pairs:
captions2 <- tibble(captions2, node_names2)
equivalencies2 <- setNames(as.list(node_names2), colnames(end_network_dep))
comms2 <- c(rep("Game Activity", 9), rep("PHQ-8", 8))

# bridge names:
posnames2 <- names(bridge_strengths_pos2[bridge_strengths_pos2 > bridge_strength_cutoff.b])
negnames2 <- names(bridge_strengths_neg2[bridge_strengths_neg2 > bridge_strength_cutoff2.b])
posnames2 <- equivalencies2[posnames2] %>% unlist()
negnames2 <- equivalencies2[negnames2] %>% unlist()

bridgenames2 <- c(posnames2, negnames2[! negnames2 %in% posnames2])
fadenames2 <- node_names2[! node_names2 %in% bridgenames2]

Plot using make_adj_plot() from sourced functions. Add on the negative layer using add_neg_edges() from same.

plot_cd_E2 <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = E2$pos_mat, adj_neg = E2$neg_mat,
                  node_labels = node_names2, 
                  node_label_col = node_font_color,
                  communities = comms2,
                  bridges_pos = bridgenames2, bridges_neg = negnames2,
                  fade = fadenames2,
                  model_parcors = E2$pcor_mat,
                  type = "cd", 
                  confirmatory = FALSE,
                  scale_labels = c("Game Endings",
                                   "PHQ-8"),
                  node_colors = pal[c(1,3)],
                  fontsize = fontsize,
                  fontawesome = FALSE)
}

plot_cd_E2(fontsize = 7)

Add the captions:

captions2 <- captions2 %>%
  rowwise() %>%
  mutate(combined = paste0(c(node_names2, captions2), collapse=": ")) %>%
  pull(combined)

cat(captions2, sep = "\n")
## Gphone: in-game phone use
## Gcomp: in-game time on computer
## Galco: in-game drinking alcohol
## Gtv: in-game TV use
## Gexer: in-game exercise
## Gcook: in-game cooking
## GhobbN: in-game new hobby
## GhobbO: in-game old hobby
## Gtime: time spent in-game
## PHQ-1: PHQ-1: little interest
## PHQ-2: PHQ-2: feeling down
## PHQ-3: PHQ-3: sleep trouble
## PHQ-4: PHQ-4: low energy
## PHQ-5: PHQ-5: appetite
## PHQ-6: PHQ-6: failure
## PHQ-7: PHQ-7: concentration
## PHQ-8: PHQ-8: psychomotor

With icons instead of names

As above, these plots use Font Awesome to replace names with images.

load.fontawesome()

node_names2FAname <- c("fa-mobile", # game phone use
                "fa-laptop", # game computer
                "fa-beer", # game drinking
                "fa-tv", # game tv
                "fa-heartbeat", # game exercise
                "fa-cutlery", # cooking
                "fa-random", # new hobby
                "fa-object-group", # hobby old
                "fa-clock-o", # end game time
                "fa-remove", # "PHQ-1: little interest"
                "fa-hand-o-down", # "PHQ-2: feeling down"
                "fa-bed", # "PHQ-3: sleep trouble"
                "fa-battery-1", # "PHQ-4: low energy"
                "fa-spoon", # "PHQ-5: appetite"
                "fa-warning", # "PHQ-6: failure"
                "fa-joomla", # "PHQ-7: concentration"
                "fa-ellipsis-h" # "PHQ-8: psychomotor agitation/slowing"
                 )
# convert to icons
node_names2FA <- fontawesome(node_names2FAname)
# provide descriptors
captions2FA <- c("in-game phone use", "in-game time on computer",
               "in-game drinking alcohol", "in-game TV use",
               "in-game exercise", "in-game cooking",
               "in-game new hobby", "in-game old hobby",
               "time spent in-game", "PHQ-1: little interest",
               "PHQ-2: feeling down", "PHQ-3: sleep trouble",
               "PHQ-4: low energy", "PHQ-5: appetite",
               "PHQ-6: failure", "PHQ-7: concentration",
               "PHQ-8: psychomotor")
# create key-value pairs:
equivalencies2FA <- setNames(as.list(node_names2FA),
                            colnames(end_network_dep))
comms2 <- c(rep("Game Activity", 9), rep("PHQ-8", 8))

# bridge names:
posnames2FA <- names(bridge_strengths_pos2[bridge_strengths_pos2 > bridge_strength_cutoff.b])
negnames2FA <- names(bridge_strengths_neg2[bridge_strengths_neg2 > bridge_strength_cutoff2.b])
posnames2FA <- equivalencies2FA[posnames2FA] %>% unlist()
negnames2FA <- equivalencies2FA[negnames2FA] %>% unlist()

bridgenames2FA <- c(posnames2FA, negnames2FA[! negnames2FA %in% posnames2FA])
fadenames2FA <- node_names2FA[! node_names2FA %in% bridgenames2FA]

Make the plot:

plot_cd_E2FA <- function(plot_node_size = node_size,
                         adj_limits = .1, fontsize = 15
                         ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = E2$pos_mat, adj_neg = E2$neg_mat,
                  node_labels = node_names2FA, 
                  node_label_col = node_font_color,
                  communities = comms2,
                  bridges_pos = bridgenames2FA, 
                  bridges_neg = negnames2FA,
                  fade = fadenames2FA,
                  model_parcors = E2$pcor_mat,
                  type = "cd", 
                  confirmatory = FALSE,
                  scale_labels = c("Game Endings",
                                   "PHQ-8"),
                  node_colors = pal[c(1,3)],
                  fontsize = fontsize,
                  fontawesome = TRUE)
}

plot_cd_E2FA(fontsize = 12)

In game:

  • : phone use
  • : time on computer
  • : alcohol use
  • : TV use
  • : in-game exercise
  • : cooking
  • : new hobby
  • : old hobby
  • : time spent

PHQ-8:

  1. PHQ-1: : Little interest or pleasure in doing things
  2. PHQ-2: : Feeling down, depressed, or hopeless
  3. PHQ-3: : Trouble falling or staying asleep, or sleeping too much
  4. PHQ-4: : Feeling tired or having little energy
  5. PHQ-5: : Poor appetite or overeating
  6. PHQ-6: : Feeling bad about yourself, or that you are a failure, or have let yourself or your family down
  7. PHQ-7: : Trouble concentrating on things, such as reading the newspaper or watching television
  8. PHQ-8: : Moving or speaking so slowly that other people could have noticed. Or the opposite - being so fidgety or restless that you have been moving around a lot more than usual

Community-independent plots (CI)

The second set of plots show the community-independent plot (CI).

plot_ci_E2 <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = E2$pos_mat, adj_neg = E2$neg_mat,
                  node_labels = node_names2, 
                  node_label_col = node_font_color,
                  communities = comms2,
                  bridges_pos = NULL, bridges_neg = NULL,
                  fade = NULL,
                  model_parcors = E2$pcor_mat,
                  type = "ci", 
                  confirmatory = FALSE,
                  scale_labels = c("Game Endings",
                                   "PHQ-8"),
                  node_colors = pal[c(1,3)],
                  fontsize = fontsize,
                  fontawesome = FALSE)
}

plot_ci_E2(fontsize = 7)

Confirmatory plots

plot_C2 <- C2$pcor_mat * C2$Adj_10 # instead of C2$pcor_mat_zero
plot_cd_C2 <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C2, 
                  node_labels = node_names2, 
                  node_label_col = node_font_color,
                  communities = comms2,
                  bridges_pos = bridgenames2, 
                  fade = fadenames2,
                  model_parcors = C2$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("Game Endings",
                                  "PHQ-8"),
                  node_colors = pal[c(1,3)],
                  fontsize = fontsize,
                  fontawesome = FALSE)
}

plot_cd_C2(fontsize = 7)

We can run this with the FontAwesome icons, too:

# plot_C2 <- C2$pcor_mat * C2$Adj_10 # instead of C2$pcor_mat_zero
plot_cd_C2_FA <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C2, 
                  node_labels = node_names2FA, 
                  node_label_col = node_font_color,
                  communities = comms2,
                  bridges_pos = bridgenames2FA, 
                  fade = fadenames2FA,
                  model_parcors = C2$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("Game Endings",
                                  "PHQ-8"),
                  node_colors = pal[c(1,3)],
                  fontsize = fontsize,
                  fontawesome = TRUE)
}

plot_cd_C2_FA(fontsize = 12)

Within-community edges

As above in C1, we can include a community-dependent plot which doesn’t mask the within-community edges, by using the variant type = "keep_within_edges" to the make_adj_plot() function. We’ll keep it for the FA plot.

plot_cd_C2_FA_within_edges <- function(plot_node_size = node_size,
                          adj_limits = .1, fontsize = 15
                          ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = TRUE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C2, 
                  node_labels = node_names2FA, 
                  node_label_col = node_font_color,
                  communities = comms2,
                  bridges_pos = bridgenames2FA, 
                  fade = fadenames2FA,
                  model_parcors = C2$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("Game Endings",
                                  "PHQ-8"),
                  node_colors = pal[c(1,3)],
                  fontsize = fontsize,
                  fontawesome = TRUE)
}

plot_cd_C2_FA_within_edges(fontsize = 12)

Network 3: PHQ-8 and Real-Life Activities

Create network in {BGGM}

Exploratory network

if(! params$models_loaded) {
  explore_network3 <- BGGM::explore(act_network_dep,
                                  type = "mixed",
                                  iter = 5000,
                                  seed = 1)
  E3 <- BGGM::select(explore_network3,
                     alternative = "exhaustive",
                     bf_cut = 3)
}

if(pacman::p_isloaded("BGGM")) {
  allp3 <- plot(E3, edge_magnify = 5, ci_width = 0.95)
  gridExtra::grid.arrange(grobs = allp3)
}
# retain positive & negative partial correlations from the PHQ/activity variables
partial_cors_pos3 <- E3$pcor_mat * E3$pos_mat
partial_cors_neg3 <- E3$pcor_mat * E3$neg_mat
#vector for nodenames
node_names3 <- colnames(act_network_dep)
#create communities
comms3 <- c(rep("Real Activity", 21), rep("PHQ", 8))
# rename columns with node names
dimnames(partial_cors_pos3) <- list(node_names3, node_names3)
dimnames(partial_cors_neg3) <- list(node_names3, node_names3)

# calculate bridge strength. comms is a vector specifying
# the community for each node
bridge_strengths_pos3 <- networktools::bridge(partial_cors_pos3, communities = comms3)$`Bridge Strength`
bridge_strengths_neg3 <- networktools::bridge(partial_cors_neg3, communities = comms3)$`Bridge Strength`

# we use the top 10% in bridge strength as bridge nodes
bridge_strength_cutoff.c <- quantile(bridge_strengths_pos3, 0.9)
bridge_strengths_pos3[bridge_strengths_pos3 > bridge_strength_cutoff.c]
## writing PHQ.8_5 
##   0.307   0.284
bridge_strength_cutoff2.c <- quantile(bridge_strengths_neg3, 0.9)
bridge_strengths_neg3[bridge_strengths_neg3 > bridge_strength_cutoff2.c]
## work_outside_home           PHQ.8_1           PHQ.8_3 
##             0.304             0.440             0.401

Confirmatory

Create the confirmatory network.

confirm_E3 <- t2 %>% select(home_exercise:work_outside_home, PHQ.8_1:PHQ.8_8)
confirm_E3$id <- NULL

if(! params$models_loaded) {
  confirm_network3 <- BGGM::explore(confirm_E3,
                                  type = "mixed",
                                  iter = 5000,
                                  seed = 1)
  C3 <- BGGM::select(confirm_network3)
}

if(pacman::p_isloaded("BGGM")) {
  allpc3 <- plot(C3, edge_magnify = 5, ci_width = 0.95)
  gridExtra::grid.arrange(grobs = allpc3, ncol = 2)
}

Plots for Network 3 (PHQ & Real-Life Activities)

Since these are larger networks, node size should return to the first size of 25 for knitting and 30 for saving.

node_size <- node_size - 5 + ifelse(params$save_all_plots, 2, 0)

Exploratory plots

# node_names3
node_names3 <- c("RexerH", "RexerO", "Rgym", "Rcook",
                 "Rvol", "Rtv", "Rvg", "Rknit", "Rread",
                 "RhobbN", "Ralco", "Rmj", "Rsubs", "Rreas",
                 "Rsmed", "Ryoga", "Rwrit", "Rmus", "Rzoom",
                 "Rwfh", "Roffic", "PHQ-1", "PHQ-2", "PHQ-3", "PHQ-4",
                 "PHQ-5", "PHQ-6", "PHQ-7", "PHQ-8")
# provide descriptors
captions3 <- c("real-life in-home exercise",
               "real-life outdoor exercise", "real-life gym",
               "real-life baking and cooking",
               "real-life volunteering",
               "real-life TV use", "real-life videogames",
               "real-life knitting", "real-life reading",
               "real-life new hobbies", "real-life drinking alcohol",
               "real-life marijuana use",
               "real-life substance use (other)",
               "real-life reassurance-seeking",
               "real-life social media use", "real-life yoga",
               "real-life writing", "real-life playing music",
               "real-life video calls with friends",
               "real-life working from homew",
               "real-life working outside the home",
               "PHQ-1: little interest",
               "PHQ-2: feeling down", "PHQ-3: sleep trouble",
               "PHQ-4: low energy", "PHQ-5: appetite",
               "PHQ-6: failure", "PHQ-7: concentration",
               "PHQ-8: psychomotor")
# create key-value pairs:
captions3 <- tibble(captions3, node_names3)
equivalencies3 <- setNames(as.list(node_names3), colnames(act_network_dep))
comms3 <- c(rep("Real-Life Activities", 21), rep("PHQ-8", 8))
# bridge names:
posnames3 <- names(bridge_strengths_pos3[bridge_strengths_pos3 > bridge_strength_cutoff.c])
negnames3 <- names(bridge_strengths_neg3[bridge_strengths_neg3 > bridge_strength_cutoff2.c])
posnames3 <- equivalencies3[posnames3] %>% unlist()
negnames3 <- equivalencies3[negnames3] %>% unlist()

bridgenames3 <- c(posnames3, negnames3[! negnames3 %in% posnames3])
fadenames3 <- node_names3[! node_names3 %in% bridgenames3]

Plot using make_adj_plot() from sourced functions. Add on the negative layer using add_neg_edges() from same.

plot_cd_E3 <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = E3$pos_mat, adj_neg = E3$neg_mat,
                  node_labels = node_names3, 
                  node_label_col = node_font_color,
                  communities = comms3,
                  bridges_pos = bridgenames3, bridges_neg = negnames3,
                  fade = fadenames3,
                  model_parcors = E3$pcor_mat,
                  type = "cd", 
                  scale_labels = c("PHQ-8",
                                   "Real-Life Activities"),
                  node_colors = pal[c(3, 2)],
                  fontsize = fontsize,
                  fontawesome = FALSE)
}

plot_cd_E3(fontsize = 7)

Add the captions:

captions3 <- captions3 %>%
  rowwise() %>%
  mutate(combined = paste0(c(node_names3, captions3), collapse=": ")) %>%
  pull(combined)

cat(captions3, sep = "\n")
## RexerH: real-life in-home exercise
## RexerO: real-life outdoor exercise
## Rgym: real-life gym
## Rcook: real-life baking and cooking
## Rvol: real-life volunteering
## Rtv: real-life TV use
## Rvg: real-life videogames
## Rknit: real-life knitting
## Rread: real-life reading
## RhobbN: real-life new hobbies
## Ralco: real-life drinking alcohol
## Rmj: real-life marijuana use
## Rsubs: real-life substance use (other)
## Rreas: real-life reassurance-seeking
## Rsmed: real-life social media use
## Ryoga: real-life yoga
## Rwrit: real-life writing
## Rmus: real-life playing music
## Rzoom: real-life video calls with friends
## Rwfh: real-life working from homew
## Roffic: real-life working outside the home
## PHQ-1: PHQ-1: little interest
## PHQ-2: PHQ-2: feeling down
## PHQ-3: PHQ-3: sleep trouble
## PHQ-4: PHQ-4: low energy
## PHQ-5: PHQ-5: appetite
## PHQ-6: PHQ-6: failure
## PHQ-7: PHQ-7: concentration
## PHQ-8: PHQ-8: psychomotor

With icons instead of names

As above, these plots use Font Awesome to replace names with images.

load.fontawesome()

node_names3FAname <- c("fa-bicycle", # home exercise
                      "fa-futbol-o", # outside exercise
                      "fa-hashtag", # gym
                      "fa-cutlery", # cooking
                      "fa-handshake-o", # volunteering
                      "fa-tv", # tv
                      "fa-gamepad", # videogames
                      "fa-connectdevelop", # knitting
                      "fa-book", # reading
                      "fa-modx", # new hobbies
                      "fa-glass", # alcohol
                      "fa-leaf", # marijuana
                      "fa-flask", # other substances fa-eye-slash?
                      "fa-hand-peace-o", # reassurance
                      "fa-twitter", # social media
                      "fa-sun-o", # yoga   # refresh?
                      "fa-pencil", # writing
                      "fa-music", # music playing
                      "fa-skype", # videocalls with friends
                      "fa-window-restore", # working from home
                      "fa-building-o", # working from the office
                      "fa-remove", # "PHQ-1: little interest"
                      "fa-hand-o-down", # "PHQ-2: feeling down"
                      "fa-bed", # "PHQ-3: sleep trouble"
                      "fa-battery-1", # "PHQ-4: low energy"
                      "fa-spoon", # "PHQ-5: appetite"
                      "fa-warning", # "PHQ-6: failure"
                      "fa-joomla", # "PHQ-7: concentration"
                      "fa-ellipsis-h" # "PHQ-8: psychomotor agitation/slowing"
                      )

# convert to icons
node_names3FA <- fontawesome(node_names3FAname)
# provide descriptors
captions3FA <- c(
               "real-life outdoor exercise", "real-life gym",
               "real-life baking and cooking",
               "real-life volunteering",
               "real-life TV use", "real-life videogames",
               "real-life knitting", "real-life reading",
               "real-life new hobbies",
               "real-life drinking alcohol",
               "real-life marijuana use",
               "real-life substance use (other)",
               "real-life reassurance-seeking",
               "real-life social media use", "real-life yoga",
               "real-life writing", "real-life playing music",
               "real-life video calls with friends",
               "real-life working from homew",
               "real-life working outside the home",
               "PHQ-1: little interest",
               "PHQ-2: feeling down", "PHQ-3: sleep trouble",
               "PHQ-4: low energy", "PHQ-5: appetite",
               "PHQ-6: failure", "PHQ-7: concentration",
               "PHQ-8: psychomotor"
               )
# create key-value pairs:
equivalencies3FA <- setNames(as.list(node_names3FA),
                            colnames(act_network_dep))
comms3 <- c(rep("Real Activity", 21), rep("PHQ-8", 8))

# bridge names:
posnames3FA <- names(bridge_strengths_pos3[bridge_strengths_pos3 > bridge_strength_cutoff.c])
negnames3FA <- names(bridge_strengths_neg3[bridge_strengths_neg3 >
                                          bridge_strength_cutoff2.c])
posnames3FA <- equivalencies3FA[posnames3FA] %>% unlist()
negnames3FA <- equivalencies3FA[negnames3FA] %>% unlist()

bridgenames3FA <- c(posnames3FA, negnames3FA[! negnames3FA %in% posnames3FA])
fadenames3FA <- node_names3FA[! node_names3FA %in% bridgenames3FA]

Make the plot:

plot_cd_E3FA <- function(plot_node_size = node_size,
                         adj_limits = .1, fontsize = 15
                         ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = E3$pos_mat, adj_neg = E3$neg_mat,
                  node_labels = node_names3FA, 
                  node_label_col = node_font_color,
                  communities = comms3,
                  bridges_pos = bridgenames3FA, 
                  bridges_neg = negnames3FA,
                  fade = fadenames3FA,
                  model_parcors = E3$pcor_mat,
                  type = "cd", 
                  scale_labels = c("PHQ-8",
                                   "Real-Life Activities"),
                  node_colors = pal[c(3, 2)],
                  fontsize = fontsize,
                  fontawesome = TRUE)
}

plot_cd_E3FA(fontsize = 12)

Real-life activities:

  • : home exercise
  • : outdoor exercise
  • : gym
  • : cooking
  • : volunteering
  • : TV use
  • : videogames
  • : knitting
  • : reading
  • : new hobbies
  • : drinking alcohol
  • : marijuana use
  • : other substance use
  • : reassurance-seeking
  • : social media use
  • : yoga
  • : writing
  • : playing music
  • : video calls with friends
  • : working from home
  • : working outside the home

PHQ-8:

  1. PHQ-1: : Little interest or pleasure in doing things
  2. PHQ-2: : Feeling down, depressed, or hopeless
  3. PHQ-3: : Trouble falling or staying asleep, or sleeping too much
  4. PHQ-4: : Feeling tired or having little energy
  5. PHQ-5: : Poor appetite or overeating
  6. PHQ-6: : Feeling bad about yourself, or that you are a failure, or have let yourself or your family down
  7. PHQ-7: : Trouble concentrating on things, such as reading the newspaper or watching television
  8. PHQ-8: : Moving or speaking so slowly that other people could have noticed. Or the opposite - being so fidgety or restless that you have been moving around a lot more than usual

Community-independent plots (CI)

These plots show the community-independent plot (CI).

plot_ci_E3 <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = E3$pos_mat, adj_neg = E3$neg_mat,
                  node_labels = node_names3, 
                  node_label_col = node_font_color,
                  communities = comms3,
                  bridges_pos = NULL, bridges_neg = NULL,
                  fade = NULL,
                  model_parcors = E3$pcor_mat,
                  type = "ci", 
                  confirmatory = FALSE,
                  scale_labels = c("PHQ-8", "Real-Life Activities"),
                  node_colors = pal[c(3, 2)],
                  fontsize = fontsize,
                  fontawesome = FALSE)
}

plot_ci_E3(fontsize = 7)

Confirmatory plots

plot_C3 <- C3$pcor_mat * C3$Adj_10 # instead of C3$pcor_mat_zero
plot_cd_C3 <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C3, 
                  node_labels = node_names3, 
                  node_label_col = node_font_color,
                  communities = comms3,
                  bridges_pos = bridgenames3, 
                  fade = fadenames3,
                  model_parcors = C3$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("PHQ-8", "Real-Life Activities"),
                  node_colors = pal[c(3, 2)],
                  fontsize = fontsize,
                  fontawesome = FALSE)
}

plot_cd_C3(fontsize = 7)

We can run this with the FontAwesome icons, too:

# plot_C3 <- C3$pcor_mat * C3$Adj_10 # instead of C3$pcor_mat_zero
plot_cd_C3_FA <- function(plot_node_size = node_size,
                       adj_limits = .1, fontsize = 15
                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = FALSE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C3, 
                  node_labels = node_names3FA, 
                  node_label_col = node_font_color,
                  communities = comms3,
                  bridges_pos = bridgenames3FA, 
                  fade = fadenames3FA,
                  model_parcors = C3$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("PHQ-8", "Real-Life Activities"),
                  node_colors = pal[c(3, 2)],
                  fontsize = fontsize,
                  fontawesome = TRUE)
}

plot_cd_C3_FA(fontsize = 12)

Within-community edges

As above in C1 and C2, we can include a community-dependent plot which doesn’t mask the within-community edges, by using the variant within = TRUE" to the make_adj_plot() function. We’ll keep it for the FA plot.

plot_cd_C3_FA_within_edges <- function(plot_node_size = node_size,
                                       adj_limits = .1, fontsize = 15
                                       ) {
  create_net_plot(plot_node_size = plot_node_size, 
                  within = TRUE,
                  adj_limits = adj_limits, 
                  adj_pos = plot_C3, 
                  node_labels = node_names3FA, 
                  node_label_col = node_font_color,
                  communities = comms3,
                  bridges_pos = bridgenames3FA, 
                  fade = fadenames3FA,
                  model_parcors = C3$pcor_mat,
                  type = "cd", 
                  confirmatory = TRUE,
                  scale_labels = c("PHQ-8", "Real-Life Activities"),
                  node_colors = pal[c(3, 2)],
                  fontsize = fontsize,
                  fontawesome = TRUE)
}

plot_cd_C3_FA_within_edges(fontsize = 12)

Manuscript plots

The following code creates the arranged plots used in the manuscript. They are combinations of plots printed above.

pacman::p_load(cowplot)

legend_1 <- ggplot(tibble(x = c(3, 12), y = 1, z = c("A", "B")), 
       aes(x, y, color = z)) +
  geom_point(size = 30) +
  scale_color_manual(values = c("#1b9e77", "#d95f02")) +
  scale_x_continuous(limits = c(0, 15)) +
  scale_y_continuous(limits = c(.8, 1.2)) +
  theme_void() + theme(legend.position = "none") +
  annotate("text", x = 3, y = .88, size = 35,
           label = "Game Endings") +
  annotate("text", x = 12, y = .88, size = 35,
           label = "Real-Life Activities")

network1_plot <- cowplot::plot_grid(
  plot_cd_EFA(plot_node_size = 35, 
              fontsize = 45,
              adj_limits = 0),
  #cowplot::get_legend(add_legend(plot_cd_EFA(), textsize = 70)),
  cowplot::plot_grid(legend_1),
  plot_cd_C1_FA_within_edges(plot_node_size = 35,
                             fontsize = 45,
                             adj_limits = 0),
  rel_heights = c(1, .2, 1),
  rel_widths  = c(1, .7, 1),
  axis = "ltrb", align = "hv",
  ncol = 1,
  labels = c('A', '', 'B'),
  label_x = 0.2,
  label_size = 100
  )

legend_2_3 <- ggplot(tibble(x = c(3, 12, 21), y = 1, 
                            z = c("A", "B", "C")), 
       aes(x, y, color = z)) +
  geom_point(size = 30) +
  scale_color_manual(values = c("#1b9e77", "#d95f02", "#7570b3")) +
  scale_x_continuous(limits = c(0, 24)) +
  scale_y_continuous(limits = c(.8, 1.2)) +
  theme_void() + theme(legend.position = "none") +
  annotate("text", x = 3, y = .88, size = 35,
           label = "Game Endings") +
  annotate("text", x = 12, y = .88, size = 35,
           label = "Real-Life Activities") +
  annotate("text", x = 21, y = .88, size = 35,
           label = "PHQ-8")

# legend_3 <- ggplot(tibble(x = c(3, 12), y = 1, z = c("A", "B")), 
#        aes(x, y, color = z)) +
#   geom_point(size = 30) +
#   scale_color_manual(values = c("#7570b3", "#d95f02")) +
#   scale_x_continuous(limits = c(0, 15)) +
#   scale_y_continuous(limits = c(.8, 1.2)) +
#   theme_void() + theme(legend.position = "none") +
#   annotate("text", x = 3, y = .88, size = 35,
#            label = "PHQ-8") +
#   annotate("text", x = 12, y = .88, size = 35,
#            label = "Real-Life Activities")

networks2_3_plot <- cowplot::plot_grid(
  cowplot::plot_grid(# network 2
    plot_cd_E2FA(plot_node_size = 40, 
                 fontsize = 50,
                 adj_limits = .05),
    plot_cd_C2_FA_within_edges(plot_node_size = 40, 
                               fontsize = 50,
                               adj_limits = .05), 
    ncol = 2,
    labels = c('A', 'B'),
    label_x = 0.2, label_size = 100
  ),
  cowplot::plot_grid(NULL, legend_2_3, NULL, nrow = 1,
                     rel_widths  = c(.6, 1, .6)),
  cowplot::plot_grid(# network 3
    plot_cd_E3FA(plot_node_size = 35, 
                 fontsize = 45,
                 adj_limits = 0),
    plot_cd_C3_FA_within_edges(plot_node_size = 35, 
                               fontsize = 45,
                               adj_limits = 0),
    ncol = 2,
    labels = c('C', 'D'),
    label_x = 0.2, label_size = 100
  ),
  # cowplot::plot_grid(NULL, legend_3, NULL, nrow = 1,
  #                    rel_widths  = c(.6, 1, .6)),
  # specs
  byrow = TRUE,
  rel_heights = c(1, .2, 1),
  nrow = 3
  )