knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)
knitr::opts_chunk$set(fig.width = 10, fig.height = 7, dpi = 300)
packages <- c("tidyverse", "pheatmap", "limma", "mixOmics", "ggrepel","ggpubr","randomForest","iml","caret","nnet")
lapply(packages, function(p) if (!requireNamespace(p, quietly = TRUE)) install.packages(p))
lapply(packages, library, character.only = TRUE)
metadata <- read.csv("Metadata.csv")
metagenomics <- read.csv("Metagenomics.csv", row.names = 1)
metatranscriptomics <- read.csv("Metatranscriptomics.csv", row.names = 1)
metaproteomics <- read.csv("Metaproteomics.csv", row.names = 1)
metabolomics <- read.csv("Metabolomics.csv", row.names = 1)

# === STEP 1: Clean sample names ===
clean_colnames <- function(df) {
   colnames(df) <- gsub("\\.", " ", colnames(df))
     return(df)
 }

  metagenomics <- clean_colnames(metagenomics)
 metatranscriptomics <- clean_colnames(metatranscriptomics)
 metaproteomics <- clean_colnames(metaproteomics)
 metabolomics <- clean_colnames(metabolomics)
 
 # === STEP 2: Align samples ===
 common_ids <- Reduce(intersect, list(
     colnames(metagenomics),
     colnames(metatranscriptomics),
     colnames(metaproteomics),
     colnames(metabolomics),
     metadata$SampleID
 ))
 
 metadata <- metadata %>%
     filter(SampleID %in% common_ids) %>%
    arrange(SampleID)
 rownames(metadata) <- metadata$SampleID
 
 omics_list <- list(
     Metagenomics = metagenomics[, metadata$SampleID],
     Metatranscriptomics = metatranscriptomics[, metadata$SampleID],
     Metaproteomics = metaproteomics[, metadata$SampleID],
     Metabolomics = metabolomics[, metadata$SampleID]
 )
 
 # === STEP 3: Transpose + Fix rownames (PLACE THIS HERE!) ===
 omics_list <- lapply(omics_list, function(df) {
     df_t <- as.data.frame(t(df))
     df_t$SampleID <- rownames(df_t)
     rownames(df_t) <- df_t$SampleID
     df_t$SampleID <- NULL
     return(df_t)
 })
plot_heatmap <- function(data, stats, title) {
  top_feats <- rownames(stats %>% arrange(FDR) %>% head(20))
  mat <- data[, top_feats]
  annotation <- metadata[rownames(mat), , drop = FALSE]
  pheatmap(mat, annotation_row = annotation["Group"],
           main = paste("Top Features -", title))
}

plot_volcano <- function(stats, title) {
  stats$Feature <- rownames(stats)
  ggplot(stats, aes(x = logFC, y = -log10(pval))) +
    geom_point(aes(color = FDR < 0.05), alpha = 0.6) +
    geom_text_repel(data = subset(stats, FDR < 0.01),
                    aes(label = Feature), size = 3, max.overlaps = 10) +
    scale_color_manual(values = c("grey", "red")) +
    theme_minimal() + labs(title = paste("Volcano Plot -", title))
}

plot_bar <- function(stats, title) {
  top <- stats %>% arrange(FDR) %>% head(10)
  top$Feature <- factor(rownames(top), levels = rownames(top))
  ggplot(top, aes(x = Feature, y = logFC, fill = FDR < 0.05)) +
    geom_col() +
    coord_flip() +
    theme_minimal() +
    labs(title = paste("Top Differential Features -", title))
}

plot_pca <- function(data, title) {
  # Remove columns with all NA values
  data <- data[, colSums(is.na(data)) < nrow(data), drop = FALSE]

  # Remove rows with any NA values
  data <- data[complete.cases(data), , drop = FALSE]

  # Check if there's enough data left to perform PCA
  if (nrow(data) < 2 || ncol(data) < 2) {
    warning(paste("Skipping PCA for", title, "- insufficient data after NA filtering."))
    return(NULL)
  }

  # Perform PCA
  pca <- prcomp(data, scale. = FALSE)

  # Get PCA scores and add Group info
  scores <- as.data.frame(pca$x)
  scores$Group <- metadata[rownames(scores), "Group"]

  # Plot the PCA
  ggplot(scores, aes(x = PC1, y = PC2, color = Group)) +
    geom_point(size = 3, alpha = 0.8) +
    theme_minimal() +
    labs(title = paste("PCA -", title), x = "PC1", y = "PC2")
}

plot_top_boxplots <- function(data, stats, title, n = 6) {
  
  
  top_feats <- rownames(stats %>% arrange(FDR) %>% head(n))
  
  long_data <- data[, top_feats] %>%
    rownames_to_column("SampleID") %>%
    pivot_longer(-SampleID, names_to = "Feature", values_to = "Value") %>%
    left_join(metadata, by = "SampleID")
  
  ggplot(long_data, aes(x = Group, y = Value, fill = Group)) +
    geom_boxplot(alpha = 0.7) +
    stat_compare_means(
      method = "t.test", 
      label = "p.signif", 
      comparisons = list(c("Case", "Control"))
    ) +
    facet_wrap(~Feature, scales = "free_y") +
    theme_minimal() +
    labs(title = paste("Top", n, "Features by Boxplot -", title))
}
for (omics_name in names(omics_list)) {
  cat("Generating plots for:", omics_name, "\n")
  data <- omics_list[[omics_name]]
  stats <- stats_results[[omics_name]]
  
  plot_heatmap(data, stats, omics_name)
  print(plot_volcano(stats, omics_name))
  print(plot_bar(stats, omics_name))
  print(plot_pca(data, omics_name))
  print(plot_top_boxplots(data, stats, omics_name))
}

X <- omics_list
Y <- factor(metadata$Group)
design <- matrix(0.1, ncol = length(X), nrow = length(X))
diag(design) <- 0

diablo_model <- block.splsda(X, Y, ncomp = 2, design = design)
plotIndiv(diablo_model, legend = TRUE, title = "DIABLO Sample Separation")

# Run the plot
plotVar(diablo_model, var.names = TRUE, title = "DIABLO Feature Loadings")

library(dplyr)
library(tidyr)
library(pheatmap)

# Load metadata
metadata <- read.csv("Metadata.csv", stringsAsFactors = FALSE)
rownames(metadata) <- metadata$SampleID

# Select your omics data and stats (example: Metagenomics)
data <- omics_list[["Metatranscriptomics"]]
stats <- stats_results[["Metatranscriptomics"]]

# Get significant features (FDR < 0.05)
sig_feats <- rownames(stats[stats$FDR < 0.95, ])
sig_data <- data[, sig_feats, drop = FALSE]

# Combine omics data and metadata
analysis_df <- cbind(metadata, sig_data)

# Binary metadata variables to test (update if needed)
binary_vars <- c("Drug_Use", "Autoimmune_Disorder","Anxiety", "Depression")
binary_results <- lapply(binary_vars, function(meta_var) {
  lapply(sig_feats, function(f) {
    test <- t.test(analysis_df[[f]] ~ analysis_df[[meta_var]])
    data.frame(Metadata = meta_var, Feature = f, Pval = test$p.value)
  }) %>% bind_rows()
}) %>% bind_rows()

binary_results$FDR <- p.adjust(binary_results$Pval, method = "BH")

# Correlation with age (continuous)
cor_results <- lapply(sig_feats, function(f) {
  test <- cor.test(analysis_df[[f]], analysis_df$Age)
  data.frame(Metadata = "Age", Feature = f, Cor = test$estimate, Pval = test$p.value)
}) %>% bind_rows()

cor_results$FDR <- p.adjust(cor_results$Pval, method = "BH")

# Combine and view top hits
all_results <- bind_rows(binary_results, cor_results)
knitr::kable(head(all_results %>% arrange(FDR), 10), digits = 4)
Metadata Feature Pval FDR Cor
…1 Drug_Use MRNA 10 0.0826 0.5564 NA
…2 Autoimmune_Disorder MRNA 89 0.0927 0.5564 NA
…3 Anxiety MRNA 7 0.0579 0.5564 NA
…4 Depression MRNA 69 0.0605 0.5564 NA
cor…5 Age MRNA 7 0.5521 0.6689 0.0880
cor…6 Age MRNA 10 0.5380 0.6689 0.0911
cor…7 Age MRNA 69 0.6689 0.6689 0.0633
cor…8 Age MRNA 89 0.6160 0.6689 -0.0742
cor…9 Age MRNA 100 0.3091 0.6689 0.1499
cor…10 Age MRNA 116 0.2029 0.6689 -0.1871
# Prepare matrix of correlations
meta_numeric <- analysis_df[, c("Drug_Use", "Autoimmune_Disorder","Anxiety", "Depression")]
meta_numeric <- sapply(meta_numeric, as.numeric)
cor_matrix <- cor(analysis_df[, sig_feats], meta_numeric, use = "pairwise.complete.obs")

# Plot
if (nrow(cor_matrix) >= 2 && ncol(cor_matrix) >= 2) {
  pheatmap(cor_matrix, main = "Correlation: Metadata vs. Metatranscriptomics Significant Features")
} else {
  pheatmap(cor_matrix, cluster_rows = FALSE, cluster_cols = FALSE,
           main = "Correlation: Metadata vs. Metatranscriptomics Significant Features")
}

# Select your omics data and stats (example: Metagenomics)
data <- omics_list[["Metagenomics"]]
stats <- stats_results[["Metagenomics"]]

# Get significant features (FDR < 0.05)
sig_feats <- rownames(stats[stats$FDR < 0.95, ])
sig_data <- data[, sig_feats, drop = FALSE]

# Combine omics data and metadata
analysis_df <- cbind(metadata, sig_data)

# Binary metadata variables to test (update if needed)
binary_vars <- c("Drug_Use", "Autoimmune_Disorder","Anxiety", "Depression")
binary_results <- lapply(binary_vars, function(meta_var) {
  lapply(sig_feats, function(f) {
    test <- t.test(analysis_df[[f]] ~ analysis_df[[meta_var]])
    data.frame(Metadata = meta_var, Feature = f, Pval = test$p.value)
  }) %>% bind_rows()
}) %>% bind_rows()

binary_results$FDR <- p.adjust(binary_results$Pval, method = "BH")

# Correlation with age (continuous)
cor_results <- lapply(sig_feats, function(f) {
  test <- cor.test(analysis_df[[f]], analysis_df$Age)
  data.frame(Metadata = "Age", Feature = f, Cor = test$estimate, Pval = test$p.value)
}) %>% bind_rows()

cor_results$FDR <- p.adjust(cor_results$Pval, method = "BH")

# Combine and view top hits
all_results <- bind_rows(binary_results, cor_results)
knitr::kable(head(all_results %>% arrange(FDR), 10), digits = 4)
Metadata Feature Pval FDR Cor
cor…1 Age Bacteria 33 0.0018 0.1237 0.4391
cor…2 Age Bacteria 29 0.0227 0.3134 -0.3283
cor…3 Age Bacteria 41 0.0184 0.3134 0.3391
cor…4 Age Bacteria 56 0.0162 0.3134 0.3454
cor…5 Age Bacteria 74 0.0141 0.3134 0.3523
cor…6 Age Bacteria 31 0.0422 0.3973 -0.2945
cor…7 Age Bacteria 34 0.0478 0.3973 -0.2872
cor…8 Age Bacteria 69 0.0518 0.3973 0.2824
cor…9 Age Bacteria 71 0.0356 0.3973 -0.3040
cor…10 Age Bacteria 55 0.0577 0.3982 0.2759
# Prepare matrix of correlations
meta_numeric <- analysis_df[, c("Drug_Use", "Autoimmune_Disorder","Anxiety", "Depression")]
meta_numeric <- sapply(meta_numeric, as.numeric)
cor_matrix <- cor(analysis_df[, sig_feats], meta_numeric, use = "pairwise.complete.obs")

# Plot
if (nrow(cor_matrix) >= 2 && ncol(cor_matrix) >= 2) {
  pheatmap(cor_matrix, main = "Correlation: Metadata vs. Metagenomics Significant Features")
} else {
  pheatmap(cor_matrix, cluster_rows = FALSE, cluster_cols = FALSE,
           main = "Correlation: Metadata vs. Metagenomics Significant Features")
}

# Select your omics data and stats (example: Metagenomics)
data <- omics_list[["Metabolomics"]]
stats <- stats_results[["Metabolomics"]]

# Get significant features (FDR < 0.05)
sig_feats <- rownames(stats[stats$FDR < 0.95, ])
sig_data <- data[, sig_feats, drop = FALSE]

# Combine omics data and metadata
analysis_df <- cbind(metadata, sig_data)

# Binary metadata variables to test (update if needed)
binary_vars <- c("Drug_Use", "Autoimmune_Disorder","Anxiety", "Depression")
binary_results <- lapply(binary_vars, function(meta_var) {
  lapply(sig_feats, function(f) {
    test <- t.test(analysis_df[[f]] ~ analysis_df[[meta_var]])
    data.frame(Metadata = meta_var, Feature = f, Pval = test$p.value)
  }) %>% bind_rows()
}) %>% bind_rows()

binary_results$FDR <- p.adjust(binary_results$Pval, method = "BH")

# Correlation with age (continuous)
cor_results <- lapply(sig_feats, function(f) {
  test <- cor.test(analysis_df[[f]], analysis_df$Age)
  data.frame(Metadata = "Age", Feature = f, Cor = test$estimate, Pval = test$p.value)
}) %>% bind_rows()

cor_results$FDR <- p.adjust(cor_results$Pval, method = "BH")

# Combine and view top hits
all_results <- bind_rows(binary_results, cor_results)
knitr::kable(head(all_results %>% arrange(FDR), 10), digits = 4)
Metadata Feature Pval FDR Cor
cor Age Metabolite 43 0.2533 0.2533 -0.1681
…2 Drug_Use Metabolite 43 0.7679 0.9097 NA
…3 Autoimmune_Disorder Metabolite 43 0.9097 0.9097 NA
…4 Anxiety Metabolite 43 0.7064 0.9097 NA
…5 Depression Metabolite 43 0.2982 0.9097 NA
# Prepare matrix of correlations
meta_numeric <- analysis_df[, c("Drug_Use", "Autoimmune_Disorder","Anxiety", "Depression")]
meta_numeric <- sapply(meta_numeric, as.numeric)
cor_matrix <- cor(analysis_df[, sig_feats], meta_numeric, use = "pairwise.complete.obs")

# Plot
if (nrow(cor_matrix) >= 2 && ncol(cor_matrix) >= 2) {
  pheatmap(cor_matrix, main = "Correlation: Metadata vs. Metabolomics Significant Features")
} else {
  pheatmap(cor_matrix, cluster_rows = FALSE, cluster_cols = FALSE,
           main = "Correlation: Metadata vs. Metabolomics Significant Features")
}

# Select your omics data and stats (example: Metagenomics)
data <- omics_list[["Metaproteomics"]]
stats <- stats_results[["Metaproteomics"]]

# Get significant features (FDR < 0.05)
sig_feats <- rownames(stats[stats$FDR < 0.95, ])
sig_data <- data[, sig_feats, drop = FALSE]

# Combine omics data and metadata
analysis_df <- cbind(metadata, sig_data)

# Binary metadata variables to test (update if needed)
binary_vars <- c("Drug_Use", "Autoimmune_Disorder","Anxiety", "Depression")
binary_results <- lapply(binary_vars, function(meta_var) {
  lapply(sig_feats, function(f) {
    test <- t.test(analysis_df[[f]] ~ analysis_df[[meta_var]])
    data.frame(Metadata = meta_var, Feature = f, Pval = test$p.value)
  }) %>% bind_rows()
}) %>% bind_rows()

binary_results$FDR <- p.adjust(binary_results$Pval, method = "BH")

# Correlation with age (continuous)
cor_results <- lapply(sig_feats, function(f) {
  test <- cor.test(analysis_df[[f]], analysis_df$Age)
  data.frame(Metadata = "Age", Feature = f, Cor = test$estimate, Pval = test$p.value)
}) %>% bind_rows()

cor_results$FDR <- p.adjust(cor_results$Pval, method = "BH")

# Combine and view top hits
all_results <- bind_rows(binary_results, cor_results)
knitr::kable(head(all_results %>% arrange(FDR), 10), digits = 4)
Metadata Feature Pval FDR Cor
cor…1 Age Protein 13 0.0047 0.1805 -0.4015
cor…2 Age Protein 29 0.0025 0.1805 -0.4259
cor…3 Age Protein 55 0.0058 0.1805 0.3923
cor…4 Age Protein 72 0.0108 0.1866 0.3649
cor…5 Age Protein 86 0.0160 0.1866 -0.3459
cor…6 Age Protein 93 0.0127 0.1866 0.3573
cor…7 Age Protein 99 0.0156 0.1866 -0.3474
cor…8 Age Protein 100 0.0090 0.1866 0.3732
cor…9 Age Protein 59 0.0198 0.1887 0.3354
cor…10 Age Protein 83 0.0203 0.1887 -0.3341
# Prepare matrix of correlations
meta_numeric <- analysis_df[, c("Drug_Use", "Autoimmune_Disorder","Anxiety", "Depression")]
meta_numeric <- sapply(meta_numeric, as.numeric)
cor_matrix <- cor(analysis_df[, sig_feats], meta_numeric, use = "pairwise.complete.obs")

# Plot
if (nrow(cor_matrix) >= 2 && ncol(cor_matrix) >= 2) {
  pheatmap(cor_matrix, main = "Correlation: Metadata vs. Metaproteomics Significant Features")
} else {
  pheatmap(cor_matrix, cluster_rows = FALSE, cluster_cols = FALSE,
           main = "Correlation: Metadata vs. Metaproteomics Significant Features")
}

Machine Learning Prediction of Case/Control

library(caret)
library(randomForest)
library(e1071)
library(xgboost)
library(pROC)
library(iml)
library(nnet)
mtx_results <- evaluate_ml_models(omics_list[["Metatranscriptomics"]], metadata)
knitr::kable(mtx_results$aucs, caption = "AUCs - Metatranscriptomics")
AUCs - Metatranscriptomics
RF SVM XGBoost Ensemble
0.5625 0.5 0.6875 0.75
mgx_results <- evaluate_ml_models(omics_list[["Metagenomics"]], metadata)
knitr::kable(mgx_results$aucs, caption = "AUCs - Metagenomics")
AUCs - Metagenomics
RF SVM XGBoost Ensemble
0.5625 0.625 0.75 0.75
mbx_results <- evaluate_ml_models(omics_list[["Metabolomics"]], metadata)
knitr::kable(mbx_results$aucs, caption = "AUCs - Metabolomics")
AUCs - Metabolomics
RF SVM XGBoost Ensemble
0.6875 0.6875 0.625 0.6875
mpx_results <- evaluate_ml_models(omics_list[["Metaproteomics"]], metadata)
knitr::kable(mpx_results$aucs, caption = "AUCs - Metaproteomics")
AUCs - Metaproteomics
RF SVM XGBoost Ensemble
0.625 0.5625 0.625 0.5
roc_mtx_rf <- roc(mtx_results$test$Group, mtx_results$rf_probs)
plot(roc_mtx_rf, col = "blue", lwd = 2, main = "ROC - Metatranscriptomics")
lines(roc(mtx_results$test$Group, mtx_results$svm_probs), col = "red", lwd = 2)
lines(roc(mtx_results$test$Group, mtx_results$xgb_probs), col = "purple", lwd = 2)
legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost"),
       col = c("blue", "red", "purple"), lwd = 2)

roc_mgx_rf <- roc(mgx_results$test$Group, mgx_results$rf_probs)
plot(roc_mgx_rf, col = "blue", lwd = 2, main = "ROC - Metagenomics")
lines(roc(mgx_results$test$Group, mgx_results$svm_probs), col = "red", lwd = 2)
lines(roc(mgx_results$test$Group, mgx_results$xgb_probs), col = "purple", lwd = 2)
legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost"),
       col = c("blue", "red", "purple"), lwd = 2)

roc_mbx_rf <- roc(mbx_results$test$Group, mbx_results$rf_probs)
plot(roc_mbx_rf, col = "blue", lwd = 2, main = "ROC - Metabolomics")
lines(roc(mbx_results$test$Group, mbx_results$svm_probs), col = "red", lwd = 2)
lines(roc(mbx_results$test$Group, mbx_results$xgb_probs), col = "purple", lwd = 2)
legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost"),
       col = c("blue", "red", "purple"), lwd = 2)

roc_mpx_rf <- roc(mpx_results$test$Group, mpx_results$rf_probs)
plot(roc_mpx_rf, col = "blue", lwd = 2, main = "ROC - Metaproteomics")
lines(roc(mpx_results$test$Group, mpx_results$svm_probs), col = "red", lwd = 2)
lines(roc(mpx_results$test$Group, mpx_results$xgb_probs), col = "purple", lwd = 2)
legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost"),
       col = c("blue", "red", "purple"), lwd = 2)

plot(roc(mtx_results$test$Group, mtx_results$rf_probs),
     col = "blue", lwd = 2, main = "ROC - Metatranscriptomics")
lines(roc(mtx_results$test$Group, mtx_results$svm_probs), col = "red", lwd = 2)
lines(roc(mtx_results$test$Group, mtx_results$xgb_probs), col = "purple", lwd = 2)

legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost"),
       col = c("blue", "red", "purple"), lwd = 2)

plot(roc(mgx_results$test$Group, mgx_results$rf_probs),
     col = "blue", lwd = 2, main = "ROC - Metagenomics")
lines(roc(mgx_results$test$Group, mgx_results$svm_probs), col = "red", lwd = 2)
lines(roc(mgx_results$test$Group, mgx_results$xgb_probs), col = "purple", lwd = 2)

legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost"),
       col = c("blue", "red", "purple"), lwd = 2)

plot(roc(mbx_results$test$Group, mbx_results$rf_probs),
     col = "blue", lwd = 2, main = "ROC - Metabolomics")
lines(roc(mbx_results$test$Group, mbx_results$svm_probs), col = "red", lwd = 2)
lines(roc(mbx_results$test$Group, mbx_results$xgb_probs), col = "purple", lwd = 2)

legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost"),
       col = c("blue", "red", "purple"), lwd = 2)

plot(roc(mpx_results$test$Group, mpx_results$rf_probs),
     col = "blue", lwd = 2, main = "ROC - Metaproteomics")
lines(roc(mpx_results$test$Group, mpx_results$svm_probs), col = "red", lwd = 2)
lines(roc(mpx_results$test$Group, mpx_results$xgb_probs), col = "purple", lwd = 2)

legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost"),
       col = c("blue", "red", "purple"), lwd = 2)

# Combine all omics data
hybrid_data <- do.call(cbind, omics_list)
hybrid_model <- evaluate_ml_models(hybrid_data, metadata)
all_omics_combined <- do.call(cbind, omics_list)
colnames(all_omics_combined) <- make.names(colnames(all_omics_combined))

hybrid_results <- evaluate_ml_models(all_omics_combined, metadata)
knitr::kable(hybrid_results$aucs, caption = "AUCs - Hybrid (All Omics Combined)")
AUCs - Hybrid (All Omics Combined)
RF SVM XGBoost Ensemble
0.625 0.5625 0.5 0.5625
plot(roc(hybrid_results$test$Group, hybrid_results$rf_probs), col = "blue", lwd = 2,
     main = "ROC - Hybrid Model (All Omics)")
lines(roc(hybrid_results$test$Group, hybrid_results$svm_probs), col = "red", lwd = 2)
lines(roc(hybrid_results$test$Group, hybrid_results$xgb_probs), col = "purple", lwd = 2)
lines(roc(hybrid_results$test$Group, 
          (hybrid_results$rf_probs + hybrid_results$svm_probs + hybrid_results$xgb_probs) / 3),
      col = "darkgreen", lwd = 2)

legend("bottomright", legend = c("Random Forest", "SVM", "XGBoost", "Ensemble"),
       col = c("blue", "red", "purple", "darkgreen"), lwd = 2)

final_auc_table <- bind_rows(
  mtx_results$aucs %>% mutate(across(everything(), as.numeric), Omics = "Metatranscriptomics"),
  mgx_results$aucs %>% mutate(across(everything(), as.numeric), Omics = "Metagenomics"),
  mbx_results$aucs %>% mutate(across(everything(), as.numeric), Omics = "Metabolomics"),
  mpx_results$aucs %>% mutate(across(everything(), as.numeric), Omics = "Metaproteomics"),
  hybrid_results$aucs %>% mutate(across(everything(), as.numeric), Omics = "Hybrid")
) %>%
  relocate(Omics) %>%
  mutate(across(where(is.numeric), round, 3))

knitr::kable(final_auc_table, caption = "Summary of AUCs Across All Omics and Models")
Summary of AUCs Across All Omics and Models
Omics RF SVM XGBoost Ensemble
Metatranscriptomics 0.562 0.500 0.688 0.750
Metagenomics 0.562 0.625 0.750 0.750
Metabolomics 0.688 0.688 0.625 0.688
Metaproteomics 0.625 0.562 0.625 0.500
Hybrid 0.625 0.562 0.500 0.562
#To interpret model performance, we generally consider the following AUC thresholds:

#- **0.90 – 1.00**: Excellent (High-performing, very predictive)
#- **0.80 – 0.89**: Good (Strong model, useful for prediction)
#- **0.70 – 0.79**: Fair (Moderate predictive power)
#- **0.60 – 0.69**: Poor (Weak, may need improvement)
#- **< 0.60**: Fail (Not useful)