2 Build graph object
Basic workflow of ggNetView:
- Build a graph object
- Understand and manipulate the graph object
- Visualize the network using layout algorithms
- Retrieve topology of network
Load R Package
2.1 Build graph from matrix
Example data
# Access built-in example datasets in ggNetView
# Raw ASV/OTU abundance table (rows = ASVs/OTUs, cols = samples)
data("otu_tab")
dim(otu_tab)## [1] 2859 18
otu_tab[1:5, 1:5]## KO1 KO2 KO3 KO4 KO5
## ASV_1 1113 1968 816 1372 1062
## ASV_2 1922 1227 2355 2218 2885
## ASV_3 568 460 899 902 1226
## ASV_4 1433 400 535 759 1287
## ASV_6 882 673 819 888 1475
# Rarefied ASV/OTU table (sequencing depth normalised by rarefaction)
data("otu_rare")
dim(otu_rare)## [1] 2859 18
otu_rare[1:5, 1:5]## KO1 KO2 KO3 KO4 KO5
## ASV_1 992 1636 604 1084 806
## ASV_2 1725 1018 1814 1743 2196
## ASV_3 520 389 687 701 932
## ASV_4 1280 328 425 580 1004
## ASV_6 794 557 633 706 1142
# Rarefied + converted to relative abundance — most common downstream input
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
# Taxonomic annotation for the ASVs/OTUs above.
# First column must be the ASV/OTU ID (matching rownames of the abundance tables).
data("tax_tab")
dim(tax_tab)## [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 directly from an abundance matrix.
# Internally: (1) optional transform -> (2) correlation -> (3) p-value adjustment
# -> (4) edge filtering -> (5) community detection -> (6) attach taxonomy.
graph_obj <- build_graph_from_mat(
mat = otu_rare_relative, # variables x samples numeric matrix
transfrom.method = "none", # input is already relative abundance
r.threshold = 0.7, # |r| cutoff (subjective; consider ggNetView_RMT)
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 # reproducibility
)
# Inspect node/edge counts and the columns now available on nodes:
# modularity, modularity2, modularity3, Modularity, Degree, Strength + taxonomy
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
2.2 Build graph from data frame
Example data
# Edge-list style example data (protein-protein interactions).
data("ppi_example")
# `df`: edge list — typically 3 columns: node1 | node2 | weight (optional)
df = ppi_example$ppi
head(df)## from to weight
## 1 A1 D40 9.306533
## 2 A2 D39 11.783920
## 3 A3 D38 23.005025
## 4 A4 D37 7.412060
## 5 A5 D36 18.778894
## 6 A6 D35 16.592965
# `node_annotation`: per-node metadata; first column = node ID
node_annotation = ppi_example$annotation
head(node_annotation)## node group
## 1 A1 A
## 2 A2 A
## 3 A3 A
## 4 A4 A
## 5 A5 A
## 6 A6 A
Build graph object
# Build a tbl_graph from an edge-list data.frame (no correlation step needed —
# edges are taken as-is from `df`). Community detection still runs on the result.
graph_obj_from_df <- build_graph_from_df(
df = df, # edge list
node_annotation = node_annotation, # per-node metadata (joined by name)
directed = F, # undirected network
module.method = "Fast_greedy", # community detection
top_modules = 15, # keep top-15 modules; rest -> "Others"
seed = 1115
)
graph_obj_from_df## # A tbl_graph: 100 nodes and 50 edges
## #
## # An unrooted forest with 50 trees
## #
## # Node Data: 100 × 9 (active)
## name group modularity modularity2 modularity3 Modularity Degree Segree
## <chr> <chr> <fct> <fct> <chr> <fct> <dbl> <dbl>
## 1 C13 C 1 1 1 1 1 1
## 2 C28 C 1 1 1 1 1 1
## 3 C2 C 10 10 10 10 1 1
## 4 D9 D 10 10 10 10 1 1
## 5 A3 A 11 11 11 11 1 1
## 6 D38 D 11 11 11 11 1 1
## 7 B12 B 12 12 12 12 1 1
## 8 D19 D 12 12 12 12 1 1
## 9 A1 A 13 13 13 13 1 1
## 10 D40 D 13 13 13 13 1 1
## # ℹ 90 more rows
## # ℹ 1 more variable: Strength <dbl>
## #
## # Edge Data: 50 × 4
## from to weight correlation
## <int> <int> <dbl> <dbl>
## 1 9 10 45.2 45.2
## 2 15 16 50.6 50.6
## 3 5 6 37.8 37.8
## # ℹ 47 more rows
# Same as above, but without any node annotation table.
# Useful when you only have an edge list and no extra metadata to attach.
graph_obj_from_df2 <- build_graph_from_df(
df = df,
node_annotation = NULL, # skip the annotation join entirely
directed = F,
module.method = "Fast_greedy",
top_modules = 15,
seed = 1115
)
graph_obj_from_df2## # A tbl_graph: 100 nodes and 50 edges
## #
## # An unrooted forest with 50 trees
## #
## # Node Data: 100 × 8 (active)
## name modularity modularity2 modularity3 Modularity Degree Segree Strength
## <chr> <fct> <fct> <chr> <fct> <dbl> <dbl> <dbl>
## 1 C13 1 1 1 1 1 1 26.7
## 2 C28 1 1 1 1 1 1 26.7
## 3 C2 10 10 10 10 1 1 37.4
## 4 D9 10 10 10 10 1 1 37.4
## 5 A3 11 11 11 11 1 1 37.8
## 6 D38 11 11 11 11 1 1 37.8
## 7 B12 12 12 12 12 1 1 41.3
## 8 D19 12 12 12 12 1 1 41.3
## 9 A1 13 13 13 13 1 1 45.2
## 10 D40 13 13 13 13 1 1 45.2
## # ℹ 90 more rows
## #
## # Edge Data: 50 × 4
## from to weight correlation
## <int> <int> <dbl> <dbl>
## 1 9 10 45.2 45.2
## 2 15 16 50.6 50.6
## 3 5 6 37.8 37.8
## # ℹ 47 more rows
2.3 Build graph from data frame with module
Example data
# Like ppi_example, but `annotation` already contains a `Modularity` column
# (i.e. module assignments computed elsewhere — we will NOT recompute them).
data("ppi_module")
df = ppi_module$ppi
head(df)## from to weight
## 1 A1 D40 9.306533
## 2 A2 D39 11.783920
## 3 A3 D38 23.005025
## 4 A4 D37 7.412060
## 5 A5 D36 18.778894
## 6 A6 D35 16.592965
node_annotation = ppi_module$annotation
head(node_annotation) # note: must contain a `Modularity` column## node Modularity
## 1 A1 A
## 2 A2 A
## 3 A3 A
## 4 A4 A
## 5 A5 A
## 6 A6 A
Build graph object
# When you already have pre-computed module assignments and want to keep them
# (e.g. from a previous WGCNA run, expert curation, biological prior),
# use the `_module` variant — it skips internal community detection and uses
# the Modularity column from `node_annotation` directly.
graph_obj_from_module <- build_graph_from_module(
df = df,
node_annotation = node_annotation, # MUST contain `Modularity` column
directed = F,
top_modules = 15,
seed = 1115
)
graph_obj_from_module## # A tbl_graph: 100 nodes and 50 edges
## #
## # An unrooted forest with 50 trees
## #
## # Node Data: 100 × 7 (active)
## name Modularity modularity2 modularity3 Degree Segree Strength
## <chr> <ord> <ord> <chr> <dbl> <dbl> <dbl>
## 1 D1 D D D 1 1 37.1
## 2 D2 D D D 1 1 63.9
## 3 D3 D D D 1 1 54.6
## 4 D4 D D D 1 1 61.7
## 5 D5 D D D 1 1 36.1
## 6 D6 D D D 1 1 71.0
## 7 D7 D D D 1 1 27.9
## 8 D8 D D D 1 1 34.6
## 9 D9 D D D 1 1 37.4
## 10 D10 D D D 1 1 63.2
## # ℹ 90 more rows
## #
## # Edge Data: 50 × 4
## from to weight correlation
## <int> <int> <dbl> <dbl>
## 1 40 91 45.2 45.2
## 2 39 92 50.6 50.6
## 3 38 93 37.8 37.8
## # ℹ 47 more rows
2.4 Build graph from adjacency matrix
Example data
# Square adjacency matrix (already-filtered weights for every node pair).
# Useful when the network was built externally (NetCoMi, FlashWeave, ...).
data("adjacency_matrix_example")
dim(adjacency_matrix_example)## [1] 2859 2859
adjacency_matrix_example[1:5, 1:5]## ASV_1 ASV_2 ASV_3 ASV_4 ASV_6
## ASV_1 0 0.0000000 0 0 0.0000000
## ASV_2 0 0.0000000 0 0 0.8947427
## ASV_3 0 0.0000000 0 0 0.0000000
## ASV_4 0 0.0000000 0 0 0.0000000
## ASV_6 0 0.8947427 0 0 0.0000000
## [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 tbl_graph from a precomputed adjacency matrix.
# Community detection is run internally (Fast_greedy here) because we have
# weights but no module assignments yet.
graph_obj_adj <- build_graph_from_adj_mat(
adjacency_matrix = adjacency_matrix_example,
module.method = "Fast_greedy",
node_annotation = tax_tab,
top_modules = 15,
seed = 1115
)
graph_obj_adj## # A tbl_graph: 2049 nodes and 9602 edges
## #
## # An undirected simple graph with 100 components
## #
## # Node Data: 2,049 × 14 (active)
## name modularity modularity2 modularity3 Modularity Degree Strength Kingdom
## <chr> <fct> <ord> <chr> <ord> <dbl> <dbl> <chr>
## 1 ASV_916 1 1 1 1 58 50.5 Bacter…
## 2 ASV_777 1 1 1 1 58 48.7 Bacter…
## 3 ASV_606 1 1 1 1 55 45.8 Bacter…
## 4 ASV_740 1 1 1 1 54 47.2 Bacter…
## 5 ASV_14… 1 1 1 1 54 44.5 Bacter…
## 6 ASV_23… 1 1 1 1 54 47.4 Bacter…
## 7 ASV_15… 1 1 1 1 52 45.3 Bacter…
## 8 ASV_24… 1 1 1 1 52 43.0 Bacter…
## 9 ASV_19… 1 1 1 1 52 43.0 Bacter…
## 10 ASV_568 1 1 1 1 51 45.1 Bacter…
## # ℹ 2,039 more rows
## # ℹ 6 more variables: Phylum <chr>, Class <chr>, Order <chr>, Family <chr>,
## # Genus <chr>, Species <chr>
## #
## # Edge Data: 9,602 × 5
## from to weight correlation corr_direction
## <int> <int> <dbl> <dbl> <chr>
## 1 1771 1825 0.793 0.793 Positive
## 2 594 597 0.895 0.895 Positive
## 3 588 597 0.864 0.864 Positive
## # ℹ 9,599 more rows
2.5 Build graph from adjacency matrix with module information
# Add a pre-existing module assignment to the annotation table.
# Here we just (for demonstration) treat the Kingdom column as the module label;
# in real use, this should be your actual module assignments.
tax_tab_module <- tax_tab %>%
dplyr::mutate(Modularity = Kingdom)
# `_module` variant for adjacency input: REQUIRES `node_annotation` to contain
# a `Modularity` column. Skips community detection and uses your provided
# module assignments directly.
graph_obj_adj_module <- build_graph_from_adj_mat_module(
adjacency_matrix = adjacency_matrix_example,
node_annotation = tax_tab_module, # MUST contain `Modularity` column
top_modules = 15,
seed = 1115
)## The max module in network is 3 we use the 3 modules for next analysis
graph_obj_adj_module## # A tbl_graph: 2049 nodes and 9602 edges
## #
## # An undirected simple graph with 100 components
## #
## # Node Data: 2,049 × 14 (active)
## name Kingdom Phylum Class Order Family Genus Species Modularity modularity2
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <ord> <ord>
## 1 ASV_9… Bacter… Prote… Gamm… Unas… Unass… Unas… Unassi… Bacteria Bacteria
## 2 ASV_7… Bacter… Acido… Acid… Unas… Unass… Gp6 Unassi… Bacteria Bacteria
## 3 ASV_6… Bacter… Actin… Acti… Acti… Nocar… Marm… Unassi… Bacteria Bacteria
## 4 ASV_3… Bacter… Prote… Beta… Unas… Unass… Unas… Unassi… Bacteria Bacteria
## 5 ASV_7… Bacter… Acido… Acid… Unas… Unass… Gp16 Unassi… Bacteria Bacteria
## 6 ASV_1… Bacter… Actin… Acti… Unas… Unass… Unas… Unassi… Bacteria Bacteria
## 7 ASV_2… Bacter… Prote… Alph… Rhiz… Hypho… Rhod… Unassi… Bacteria Bacteria
## 8 ASV_25 Bacter… Verru… Spar… Unas… Unass… Spar… Unassi… Bacteria Bacteria
## 9 ASV_7… Bacter… Actin… Acti… Acti… Cellu… Cell… Cellul… Bacteria Bacteria
## 10 ASV_1… Bacter… Acido… Acid… Unas… Unass… Gp3 Unassi… Bacteria Bacteria
## # ℹ 2,039 more rows
## # ℹ 4 more variables: modularity3 <chr>, Degree <dbl>, Segree <dbl>,
## # Strength <dbl>
## #
## # Edge Data: 9,602 × 5
## from to weight correlation corr_direction
## <int> <int> <dbl> <dbl> <chr>
## 1 1211 1492 0.793 0.793 Positive
## 2 323 2013 0.895 0.895 Positive
## 3 267 2013 0.864 0.864 Positive
## # ℹ 9,599 more rows
2.6 Build graph from double matrix
Example data
# Two abundance matrices on the SAME samples but DIFFERENT feature sets,
# typically used for cross-kingdom networks (e.g. bacteria <-> fungi).
# Bacterial ASV table
data("BASV_tab")
dim(BASV_tab)## [1] 50 10
BASV_tab[1:5, 1:5]## Sample1 Sample2 Sample3 Sample4 Sample5
## BASV1 7.769249 14.676091 6.822246 11.806957 12.086254
## BASV2 10.771846 7.749385 14.966987 7.486507 12.645461
## BASV3 11.746937 10.023547 10.025906 11.967562 8.748440
## BASV4 8.210859 4.408296 10.070862 8.954202 14.639298
## BASV5 9.833271 9.776280 10.465463 8.380012 8.905738
## [1] 50 10
FASV_tab[1:5, 1:5]## Sample1 Sample2 Sample3 Sample4 Sample5
## FASV1 8.195641 7.715472 13.247401 10.419618 11.961410
## FASV2 10.032701 12.427388 7.693471 10.711077 12.157527
## FASV3 10.109549 11.891917 9.607849 8.256637 9.989264
## FASV4 9.817056 8.038730 5.519155 7.601228 12.688531
## FASV5 13.370263 9.795554 13.639041 11.071635 8.176218
# Combined node annotation table covering BOTH feature sets above.
data("double_mat_node_df")
dim(double_mat_node_df)## [1] 100 2
head(double_mat_node_df)## name type
## 1 BASV1 Bacterial
## 2 BASV2 Bacterial
## 3 BASV3 Bacterial
## 4 BASV4 Bacterial
## 5 BASV5 Bacterial
## 6 BASV6 Bacterial
Build graph object
# Cross-domain bipartite-style network:
# correlations are computed BETWEEN features in mat1 and features in mat2
# (no within-mat1 / within-mat2 edges), then thresholded, modularised, joined
# with node annotation.
graph_obj_double_mat <- build_graph_from_double_mat(
mat1 = BASV_tab, # set A (e.g. bacteria)
mat2 = FASV_tab, # set B (e.g. fungi)
module.method = "Fast_greedy",
node_annotation = double_mat_node_df,
top_modules = 15,
seed = 1115
)## The max module in network is 4 we use the 4 modules for next analysis
graph_obj_double_mat## # A tbl_graph: 100 nodes and 2500 edges
## #
## # A bipartite simple graph with 1 component
## #
## # Node Data: 100 × 9 (active)
## name type modularity modularity2 modularity3 Modularity Degree Segree
## <chr> <chr> <fct> <fct> <chr> <fct> <dbl> <dbl>
## 1 BASV3 Bacterial 1 1 1 1 50 50
## 2 BASV6 Bacterial 1 1 1 1 50 50
## 3 BASV8 Bacterial 1 1 1 1 50 50
## 4 BASV13 Bacterial 1 1 1 1 50 50
## 5 BASV17 Bacterial 1 1 1 1 50 50
## 6 BASV19 Bacterial 1 1 1 1 50 50
## 7 BASV25 Bacterial 1 1 1 1 50 50
## 8 BASV26 Bacterial 1 1 1 1 50 50
## 9 BASV27 Bacterial 1 1 1 1 50 50
## 10 BASV31 Bacterial 1 1 1 1 50 50
## # ℹ 90 more rows
## # ℹ 1 more variable: Strength <dbl>
## #
## # Edge Data: 2,500 × 5
## from to weight correlation corr_direction
## <int> <int> <dbl> <dbl> <chr>
## 1 15 57 0.338 -0.338 Negative
## 2 57 90 0.648 0.648 Positive
## 3 16 57 0.162 0.162 Positive
## # ℹ 2,497 more rows
2.7 Build graph from igraph object
# Load the PPI example dataset (edge list + node annotation).
data("ppi_example")
# First build a native igraph object directly from the edge list.
# This is what users typically already have when they come from an igraph workflow.
igraph_object <- igraph::graph_from_data_frame(
d = ppi_example$ppi, # edge list
vertices = ppi_example$annotation, # vertex metadata
directed = FALSE
)
igraph_object## IGRAPH 32738cf UNW- 100 200 --
## + attr: name (v/c), group (v/c), weight (e/n)
## + edges from 32738cf (vertex names):
## [1] A1 --D40 A2 --D39 A3 --D38 A4 --D37 A5 --D36 A6 --D35 A7 --D34 A8 --D33
## [9] A9 --D32 A10--D31 B1 --D30 B2 --D29 B3 --D28 B4 --D27 B5 --D26 B6 --D25
## [17] B7 --D24 B8 --D23 B9 --D22 B10--D21 B11--D20 B12--D19 B13--D18 B14--D17
## [25] B15--D16 B16--D15 B17--D14 B18--D13 B19--D12 B20--D11 C1 --D10 C2 --D9
## [33] C3 --D8 C4 --D7 C5 --D6 C6 --D5 C7 --D4 C8 --D3 C9 --D2 C10--D1
## [41] C11--C30 C12--C29 C13--C28 C14--C27 C15--C26 C16--C25 C17--C24 C18--C23
## [49] C19--C22 C20--C21 C20--C21 C19--C22 C18--C23 C17--C24 C16--C25 C15--C26
## [57] C14--C27 C13--C28 C12--C29 C11--C30 C10--D1 C9 --D2 C8 --D3 C7 --D4
## + ... omitted several edges
# Convert an existing igraph object into a ggNetView-compatible tbl_graph.
# Adds Modularity / Degree / Strength columns and harmonises the schema so it
# can be plugged straight into ggNetView().
graph_obj_from_igraph <- build_graph_from_igraph(
igraph = igraph_object,
module.method = "Fast_greedy",
seed = 1115
)
graph_obj_from_igraph## # A tbl_graph: 100 nodes and 50 edges
## #
## # An unrooted forest with 50 trees
## #
## # Node Data: 100 × 8 (active)
## name group modularity modularity2 modularity3 Modularity Degree Strength
## <chr> <chr> <fct> <ord> <chr> <ord> <dbl> <dbl>
## 1 C13 C 1 1 1 1 1 26.7
## 2 C28 C 1 1 1 1 1 26.7
## 3 C2 C 10 10 10 10 1 37.4
## 4 D9 D 10 10 10 10 1 37.4
## 5 A3 A 11 11 11 11 1 37.8
## 6 D38 D 11 11 11 11 1 37.8
## 7 B12 B 12 12 12 12 1 41.3
## 8 D19 D 12 12 12 12 1 41.3
## 9 A1 A 13 13 13 13 1 45.2
## 10 D40 D 13 13 13 13 1 45.2
## # ℹ 90 more rows
## #
## # Edge Data: 50 × 3
## from to weight
## <int> <int> <dbl>
## 1 9 10 45.2
## 2 15 16 50.6
## 3 5 6 37.8
## # ℹ 47 more rows
2.8 Build graph from WGCNA
# Workflow for importing an existing WGCNA pipeline output.
# (Not evaluated here because it requires external files saved by WGCNA::blockwiseModules.)
# 1. Load the topological overlap matrix (TOM) saved by WGCNA.
load(file = "WGCNA.tom-block.1.RData")
TOM_mat <- as.matrix(TOM)
# 2. Load the abundance matrix used to build that TOM (for any downstream
# re-thresholding / sanity checks).
plot.mat = readRDS(file = "plot.mat.Rds")
# 3. Sparsify the TOM: keep only the top_k strongest TOM connections per node.
# `trans_TOM_in_WGCNA()` is a helper bundled with ggNetView for this step.
trans_TOM <- trans_TOM_in_WGCNA(TOM_mat, plot.mat, top_k = 1)
# 4. Load the WGCNA net object (contains module colour assignments).
net <- readRDS(file = "net.Rds")
# 5. Build the module table — one row per feature, columns: ID + Module.
module <- data.frame(
ID = names(net$colors),
Module = as.character(net$colors)
)
# 6. Optional ordering of node IDs (used as node_annotation here).
id <- data.frame(
ID = names(sort(net$colors))
)
# 7. Assemble the tbl_graph: uses the sparsified TOM as edge weights and the
# WGCNA module colours as the Modularity assignment (no recomputation).
obj <- build_graph_from_wgcna(
wgcna_tom = trans_TOM,
module = module,
node_annotation = id
)
obj
2.9 Build graph from multi-graph
# Consensus network workflow:
# (1) Build per-method networks on the SAME matrix.
# (2) Convert each tbl_graph back to an adjacency matrix.
# (3) Fuse the per-method adjacencies into ONE consensus tbl_graph.
# Restrict to the 40 most abundant OTUs to keep this chunk responsive.
data(otu_rare_relative)
mat <- as.matrix(otu_rare_relative)
mat <- mat[order(rowSums(mat), decreasing = TRUE)[seq_len(40)], ]
# ---- (1) Three per-method networks on the same data ----
# Spearman correlation through psych::corr.test — baseline.
g_cor <- build_graph_from_mat(mat, method = "cor", cor.method = "spearman",
proc = "BH", r.threshold = 0.4, p.threshold = 0.05,
module.method = "Fast_greedy", seed = 1)## The max module in network is 5 we use the 5 modules for next analysis
# WGCNA-style correlation (WGCNA::corAndPvalue + the package's thresholding).
g_wgcna <- build_graph_from_mat(mat, method = "WGCNA", cor.method = "spearman",
proc = "BH", r.threshold = 0.4, p.threshold = 0.05,
module.method = "Fast_greedy", seed = 1)## The max module in network is 6 we use the 6 modules for next analysis
# Hmisc::rcorr — yet another correlation engine, slightly different tie/NA behaviour.
g_hmisc <- build_graph_from_mat(mat, method = "Hmisc", cor.method = "spearman",
r.threshold = 0.4, p.threshold = 0.05,
module.method = "Fast_greedy", seed = 1)## The max module in network is 4 we use the 4 modules for next analysis
# ---- (2) tbl_graph -> adjacency matrix ----
# `get_graph_adjacency()` recovers the weighted adjacency matrix from a tbl_graph,
# which is the format expected by build_graph_from_consensus().
adj_cor <- get_graph_adjacency(g_cor)
adj_wgcna <- get_graph_adjacency(g_wgcna)
adj_hmisc <- get_graph_adjacency(g_hmisc)
# Bundle the per-method matrices into a named list. The names ("cor", "wgcna",
# "hmisc") are kept as method labels in subsequent reports.
adj_list <- list(cor = adj_cor, wgcna = adj_wgcna, hmisc = adj_hmisc)
# ---- (3) Consensus fusion ----
# Borda rank fusion: ranks every pair by |w| in each method, averages the ranks,
# then min-max rescales to [-1, 1]. Robust to across-method weight-scale differences.
g_borda <- build_graph_from_consensus(
adj_list = adj_list,
method = "rank_fusion",
rank_fusion_algorithm = "borda",
threshold = 0.5, # final |w| cutoff applied to the fused matrix
top_modules = 5,
seed = 1
)## The max module in network is 3 we use the 3 modules for next analysis
g_borda## # A tbl_graph: 8 nodes and 8 edges
## #
## # An undirected simple graph with 3 components
## #
## # Node Data: 8 × 7 (active)
## name modularity modularity2 modularity3 Modularity Degree Strength
## <chr> <fct> <ord> <chr> <ord> <dbl> <dbl>
## 1 ASV_6 1 1 1 1 3 2.33
## 2 ASV_10 1 1 1 1 3 2.33
## 3 ASV_2 1 1 1 1 3 2.33
## 4 ASV_17 1 1 1 1 3 2.33
## 5 ASV_36 2 2 2 2 1 1
## 6 ASV_38 2 2 2 2 1 1
## 7 ASV_33 3 3 3 3 1 1
## 8 ASV_37 3 3 3 3 1 1
## #
## # Edge Data: 8 × 5
## from to weight correlation corr_direction
## <int> <int> <dbl> <dbl> <chr>
## 1 1 2 0.667 0.667 Positive
## 2 1 3 0.667 0.667 Positive
## 3 1 4 1 1 Positive
## # ℹ 5 more rows