4 Get network information
Once the graph object is constructed, basic network information can be retrieved, and subnetworks can be extracted.
Load R Package
library(tidyverse) # data manipulation / piping utilities
library(ggNetView) # graph builders + info-extraction helpersExample data
# ---- Built-in example datasets ----
# Relative abundance table of rarefied ASVs/OTUs (rows = ASVs, cols = samples).
data("otu_rare_relative")
dim(otu_rare_relative)## [1] 2859 18
otu_rare_relative[1:5, 1:5]## KO1 KO2 KO3 KO4 KO5
## ASV_1 0.03306667 0.05453333 0.02013333 0.03613333 0.02686667
## ASV_2 0.05750000 0.03393333 0.06046667 0.05810000 0.07320000
## ASV_3 0.01733333 0.01296667 0.02290000 0.02336667 0.03106667
## ASV_4 0.04266667 0.01093333 0.01416667 0.01933333 0.03346667
## ASV_6 0.02646667 0.01856667 0.02110000 0.02353333 0.03806667
## [1] 2859 8
tax_tab[1:5, 1:5]## # A tibble: 5 × 5
## OTUID Kingdom Phylum Class Order
## <chr> <chr> <chr> <chr> <chr>
## 1 ASV_2 Archaea Thaumarchaeota Unassigned Nitrososphaerales
## 2 ASV_3 Bacteria Verrucomicrobia Spartobacteria Unassigned
## 3 ASV_31 Bacteria Actinobacteria Actinobacteria Actinomycetales
## 4 ASV_27 Archaea Thaumarchaeota Unassigned Nitrososphaerales
## 5 ASV_9 Bacteria Unassigned Unassigned Unassigned
Build graph object
# ---- Build a co-occurrence network as the input for downstream queries ----
graph_obj <- build_graph_from_mat(
mat = otu_rare_relative, # variables x samples numeric matrix
transfrom.method = "none", # input already relative abundance, no extra transform
r.threshold = 0.7, # |r| cutoff for keeping an edge
p.threshold = 0.05, # adjusted p-value cutoff
method = "WGCNA", # correlation backend: WGCNA::corAndPvalue
cor.method = "pearson", # Pearson correlation
proc = "bonferroni", # multiple-testing correction
module.method = "Fast_greedy", # community detection algorithm
node_annotation = tax_tab, # taxonomy joined onto each node by name
top_modules = 15, # keep top-15 modules; rest -> "Others"
seed = 1115 # fix RNG for reproducibility
)
graph_obj## # A tbl_graph: 213 nodes and 844 edges
## #
## # An undirected simple graph with 29 components
## #
## # Node Data: 213 × 14 (active)
## name modularity modularity2 modularity3 Modularity Degree Strength Kingdom
## <chr> <fct> <ord> <chr> <ord> <dbl> <dbl> <chr>
## 1 ASV_649 5 5 5 5 27 26.5 Bacter…
## 2 ASV_705 5 5 5 5 27 26.5 Bacter…
## 3 ASV_12… 5 5 5 5 27 26.5 Bacter…
## 4 ASV_13… 5 5 5 5 27 26.5 Bacter…
## 5 ASV_14… 5 5 5 5 27 26.5 Bacter…
## 6 ASV_14… 5 5 5 5 27 26.5 Bacter…
## 7 ASV_24… 5 5 5 5 27 26.5 Bacter…
## 8 ASV_25… 5 5 5 5 27 26.4 Bacter…
## 9 ASV_28… 5 5 5 5 27 26.5 Bacter…
## 10 ASV_28… 5 5 5 5 27 26.5 Bacter…
## # ℹ 203 more rows
## # ℹ 6 more variables: Phylum <chr>, Class <chr>, Order <chr>, Family <chr>,
## # Genus <chr>, Species <chr>
## #
## # Edge Data: 844 × 5
## from to weight correlation corr_direction
## <int> <int> <dbl> <dbl> <chr>
## 1 194 195 0.959 0.959 Positive
## 2 185 208 0.954 0.954 Positive
## 3 185 213 0.957 0.957 Positive
## # ℹ 841 more rows
4.1 Full-network information
# ---- Retrieve node-level and edge-level info for the FULL graph ----
# Returns a list with `node_info` and `edge_info` tibbles.
graph_obj_info <- get_info_from_graph(graph_obj = graph_obj)
class(graph_obj_info) # "list"## [1] "list"
names(graph_obj_info) # "node_info", "edge_info"## [1] "node_info" "edge_info"
graph_obj_info$node_info # per-node attributes: name, Modularity, Degree, Strength, taxonomy, ...## # A tibble: 213 × 11
## name Modularity Degree Strength Kingdom Phylum Class Order Family Genus
## <chr> <ord> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 ASV_649 5 27 26.5 Bacteria Proteo… Alph… Rhiz… Unass… Unas…
## 2 ASV_705 5 27 26.5 Bacteria Actino… Acti… Acti… Cellu… Cell…
## 3 ASV_1234 5 27 26.5 Bacteria Gemmat… Gemm… Gemm… Gemma… Gemm…
## 4 ASV_1373 5 27 26.5 Bacteria Actino… Acti… Soli… Solir… Soli…
## 5 ASV_1479 5 27 26.5 Bacteria Verruc… Spar… Unas… Unass… Spar…
## 6 ASV_1481 5 27 26.5 Bacteria Proteo… Gamm… Unas… Unass… Unas…
## 7 ASV_2453 5 27 26.5 Bacteria Bacter… Sphi… Sphi… Chiti… Unas…
## 8 ASV_2562 5 27 26.4 Bacteria Bacter… Sphi… Sphi… Chiti… Unas…
## 9 ASV_2848 5 27 26.5 Bacteria Planct… Plan… Plan… Planc… Unas…
## 10 ASV_2844 5 27 26.5 Bacteria Proteo… Unas… Unas… Unass… Unas…
## # ℹ 203 more rows
## # ℹ 1 more variable: Species <chr>
graph_obj_info$edge_info # per-edge attributes: from, to, weight, ...## # A tibble: 844 × 5
## from to weight correlation corr_direction
## <chr> <chr> <dbl> <dbl> <chr>
## 1 ASV_6 ASV_39 0.959 0.959 Positive
## 2 ASV_20 ASV_1852 0.954 0.954 Positive
## 3 ASV_20 ASV_2911 0.957 0.957 Positive
## 4 ASV_172 ASV_43 0.969 0.969 Positive
## 5 ASV_614 ASV_65 0.943 0.943 Positive
## 6 ASV_69 ASV_173 0.995 0.995 Positive
## 7 ASV_69 ASV_206 0.994 0.994 Positive
## 8 ASV_69 ASV_744 0.976 0.976 Positive
## 9 ASV_945 ASV_69 0.985 0.985 Positive
## 10 ASV_69 ASV_1418 0.975 0.975 Positive
## # ℹ 834 more rows
4.2 Sub-network (modularity) information
# ---- Split the graph by `Modularity` (one subgraph per module) ----
# `select_module = NULL` -> no merged subgraph; only per-module split + stats.
subgraph_info <- get_subgraph(
graph_obj = graph_obj, # input tbl_graph (must have a `Modularity` column on nodes)
select_module = NULL # NULL -> don't build a merged subgraph
)## Module Number
## 1 5 31
## 2 2 24
## 3 8 22
## 4 21 15
## 5 1 13
## 6 3 11
## 7 4 11
## 8 6 11
## 9 25 8
## 10 7 6
## 11 12 5
## 12 22 5
## 13 10 4
## 14 11 4
## 15 15 4
## 16 Others 39
class(subgraph_info) # "list"## [1] "list"
names(subgraph_info) # "sub_graph_all", "stat_module", "sub_graph_select"## [1] "sub_graph_all" "stat_module" "sub_graph_select"
# Per-module node counts (data.frame with columns: Module, Number).
subgraph_info$stat_module## Module Number
## 1 5 31
## 2 2 24
## 3 8 22
## 4 21 15
## 5 1 13
## 6 3 11
## 7 4 11
## 8 6 11
## 9 25 8
## 10 7 6
## 11 12 5
## 12 22 5
## 13 10 4
## 14 11 4
## 15 15 4
## 16 Others 39
We select modulerity 5
# ---- Build a merged subgraph for a chosen module ----
# `select_module = "5"` keeps nodes whose Modularity == "5"
# (and the edges between them) in `sub_graph_select`.
graph_module5 <- get_subgraph(
graph_obj = graph_obj,
select_module = "5" # character vector of module labels to retain
)## Module Number
## 1 5 31
## 2 2 24
## 3 8 22
## 4 21 15
## 5 1 13
## 6 3 11
## 7 4 11
## 8 6 11
## 9 25 8
## 10 7 6
## 11 12 5
## 12 22 5
## 13 10 4
## 14 11 4
## 15 15 4
## 16 Others 39
# ---- Inspect the module-5 subgraph using the same info helper ----
graph_obj_info <- get_info_from_graph(
graph_obj = graph_module5$sub_graph_select # the merged tbl_graph for module 5
)
class(graph_obj_info) # "list"## [1] "list"
names(graph_obj_info) # "node_info", "edge_info"## [1] "node_info" "edge_info"
graph_obj_info$node_info # nodes belonging to module 5## # A tibble: 31 × 11
## name Modularity Degree Strength Kingdom Phylum Class Order Family Genus
## <chr> <ord> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 ASV_649 5 27 26.5 Bacteria Proteo… Alph… Rhiz… Unass… Unas…
## 2 ASV_705 5 27 26.5 Bacteria Actino… Acti… Acti… Cellu… Cell…
## 3 ASV_1234 5 27 26.5 Bacteria Gemmat… Gemm… Gemm… Gemma… Gemm…
## 4 ASV_1373 5 27 26.5 Bacteria Actino… Acti… Soli… Solir… Soli…
## 5 ASV_1479 5 27 26.5 Bacteria Verruc… Spar… Unas… Unass… Spar…
## 6 ASV_1481 5 27 26.5 Bacteria Proteo… Gamm… Unas… Unass… Unas…
## 7 ASV_2453 5 27 26.5 Bacteria Bacter… Sphi… Sphi… Chiti… Unas…
## 8 ASV_2562 5 27 26.4 Bacteria Bacter… Sphi… Sphi… Chiti… Unas…
## 9 ASV_2848 5 27 26.5 Bacteria Planct… Plan… Plan… Planc… Unas…
## 10 ASV_2844 5 27 26.5 Bacteria Proteo… Unas… Unas… Unass… Unas…
## # ℹ 21 more rows
## # ℹ 1 more variable: Species <chr>
graph_obj_info$edge_info # edges between module-5 nodes## # A tibble: 330 × 5
## from to weight correlation corr_direction
## <chr> <chr> <dbl> <dbl> <chr>
## 1 ASV_244 ASV_367 0.949 0.949 Positive
## 2 ASV_1119 ASV_244 0.952 0.952 Positive
## 3 ASV_1531 ASV_244 0.965 0.965 Positive
## 4 ASV_649 ASV_322 0.958 0.958 Positive
## 5 ASV_705 ASV_322 0.954 0.954 Positive
## 6 ASV_913 ASV_322 0.954 0.954 Positive
## 7 ASV_996 ASV_322 0.949 0.949 Positive
## 8 ASV_1234 ASV_322 0.962 0.962 Positive
## 9 ASV_1373 ASV_322 0.958 0.958 Positive
## 10 ASV_1479 ASV_322 0.958 0.958 Positive
## # ℹ 320 more rows
4.3 Sub-network (sample) information
# ---- Extract sample-level subgraphs ------------------------------------
# For each sample (column of `mat`), an OTU is treated as "present" when
# its abundance is > `min_abundance` (default 0). The induced subgraph of
# `graph_obj` on those present OTUs is returned per sample. With
# `select_sample` + `combine`, a single merged subgraph is also returned.
res <- get_sample_subgraph(
graph_obj = graph_obj, # the network built above
mat = otu_rare_relative, # same matrix used to judge "presence" (rownames must match node names)
select_sample = colnames(otu_rare_relative)[1:3], # sample IDs to merge into one subgraph (here: first 3 samples)
combine = "union" # "union" = OTUs present in ANY selected sample; "intersect" = OTUs present in ALL
)
names(res) # "sub_graph_all", "stat_sample", "sub_graph_select"## [1] "sub_graph_all" "stat_sample" "sub_graph_select"
# ---- Inspect the merged 3-sample subgraph ----
res$sub_graph_select # tbl_graph: nodes = union/intersect of present OTUs across the 3 samples## # A tbl_graph: 181 nodes and 602 edges
## #
## # An undirected simple graph with 34 components
## #
## # Node Data: 181 × 16 (active)
## name modularity modularity2 modularity3 Modularity Degree Strength Kingdom
## <chr> <fct> <ord> <chr> <ord> <dbl> <dbl> <chr>
## 1 ASV_649 5 5 5 5 27 26.5 Bacter…
## 2 ASV_705 5 5 5 5 27 26.5 Bacter…
## 3 ASV_12… 5 5 5 5 27 26.5 Bacter…
## 4 ASV_13… 5 5 5 5 27 26.5 Bacter…
## 5 ASV_14… 5 5 5 5 27 26.5 Bacter…
## 6 ASV_14… 5 5 5 5 27 26.5 Bacter…
## 7 ASV_24… 5 5 5 5 27 26.5 Bacter…
## 8 ASV_25… 5 5 5 5 27 26.4 Bacter…
## 9 ASV_28… 5 5 5 5 27 26.5 Bacter…
## 10 ASV_28… 5 5 5 5 27 26.5 Bacter…
## # ℹ 171 more rows
## # ℹ 8 more variables: Phylum <chr>, Class <chr>, Order <chr>, Family <chr>,
## # Genus <chr>, Species <chr>, n_present_samples <int>,
## # present_in_samples <chr>
## #
## # Edge Data: 602 × 5
## from to weight correlation corr_direction
## <int> <int> <dbl> <dbl> <chr>
## 1 164 165 0.959 0.959 Positive
## 2 158 181 0.957 0.957 Positive
## 3 145 147 0.969 0.969 Positive
## # ℹ 599 more rows
graph_obj_info <- get_info_from_graph(graph_obj = res$sub_graph_select)
graph_obj_info$node_info # node attributes + n_present_samples / present_in_samples columns## # A tibble: 181 × 13
## name Modularity Degree Strength Kingdom Phylum Class Order Family Genus
## <chr> <ord> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 ASV_649 5 27 26.5 Bacteria Proteo… Alph… Rhiz… Unass… Unas…
## 2 ASV_705 5 27 26.5 Bacteria Actino… Acti… Acti… Cellu… Cell…
## 3 ASV_1234 5 27 26.5 Bacteria Gemmat… Gemm… Gemm… Gemma… Gemm…
## 4 ASV_1373 5 27 26.5 Bacteria Actino… Acti… Soli… Solir… Soli…
## 5 ASV_1479 5 27 26.5 Bacteria Verruc… Spar… Unas… Unass… Spar…
## 6 ASV_1481 5 27 26.5 Bacteria Proteo… Gamm… Unas… Unass… Unas…
## 7 ASV_2453 5 27 26.5 Bacteria Bacter… Sphi… Sphi… Chiti… Unas…
## 8 ASV_2562 5 27 26.4 Bacteria Bacter… Sphi… Sphi… Chiti… Unas…
## 9 ASV_2848 5 27 26.5 Bacteria Planct… Plan… Plan… Planc… Unas…
## 10 ASV_2844 5 27 26.5 Bacteria Proteo… Unas… Unas… Unass… Unas…
## # ℹ 171 more rows
## # ℹ 3 more variables: Species <chr>, n_present_samples <int>,
## # present_in_samples <chr>
graph_obj_info$edge_info # induced edges between surviving nodes## # A tibble: 602 × 5
## from to weight correlation corr_direction
## <chr> <chr> <dbl> <dbl> <chr>
## 1 ASV_6 ASV_39 0.959 0.959 Positive
## 2 ASV_20 ASV_2911 0.957 0.957 Positive
## 3 ASV_172 ASV_43 0.969 0.969 Positive
## 4 ASV_614 ASV_65 0.943 0.943 Positive
## 5 ASV_69 ASV_173 0.995 0.995 Positive
## 6 ASV_69 ASV_206 0.994 0.994 Positive
## 7 ASV_69 ASV_744 0.976 0.976 Positive
## 8 ASV_945 ASV_69 0.985 0.985 Positive
## 9 ASV_69 ASV_1418 0.975 0.975 Positive
## 10 ASV_69 ASV_2350 0.967 0.967 Positive
## # ℹ 592 more rows