Skip to main content

network-meta-analysis

Network meta-analysis in R, including network setup, consistency, treatment rankings, and league tables.

Jump to install

Source facts

Repository
choxos/BiostatAgent
Last source activity
May 27, 2026 at 20:44
Detected SKILL.md language
English
Stars
11
Forks
1

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
network-meta-analysis
description
Network meta-analysis in R, including network setup, consistency, treatment rankings, and league tables.
# Network Meta-Analysis in R ## Overview Network meta-analysis (NMA) methods for comparing multiple treatments simultaneously using direct and indirect evidence. Covers network structure assessment, frequentist and Bayesian NMA approaches, consistency evaluation, treatment rankings, and visualization techniques. ## Network Structure and Data Preparation ### Pairwise Data Format ```r library(netmeta) # Standard pairwise format for contrast-based NMA pairwise_data <- data.frame( study = c("Study1", "Study1", "Study2", "Study2", "Study3", "Study3", "Study4", "Study4", "Study5", "Study5", "Study5"), treat1 = c("A", "A", "A", "B", "B", "B", "A", "C", "A", "B", "C"), treat2 = c("B", "C", "B", "C", "C", "D", "C", "D", "B", "C", "D"), TE = c(0.5, 0.3, 0.4, -0.2, 0.1, 0.3, 0.35, 0.25, 0.45, -0.15, 0.2), seTE = c(0.1, 0.12, 0.11, 0.13, 0.15, 0.14, 0.09, 0.11, 0.10, 0.12, 0.13) ) # Create network meta-analysis object net <- netmeta( TE = TE, seTE = seTE, treat1 = treat1, treat2 = treat2, studlab = study, data = pairwise_data, sm = "MD", # Effect measure reference.group = "A", # Reference treatment all.treatments = NULL # Auto-detect ) summary(net) ``` ### Arm-Level Data Format ```r library(netmeta) # Convert arm-level to pairwise format arm_data <- data.frame( study = rep(c("S1", "S2", "S3"), c(2, 3, 2)), treatment = c("A", "B", "A", "B", "C", "B", "C"), n = c(50, 52, 48, 51, 49, 55, 53), events = c(15, 22, 12, 25, 18, 28, 20) ) # Use pairwise() to convert library(meta) pw <- pairwise( treat = treatment, event = events, n = n, studlab = study, data = arm_data, sm = "OR" ) # Create network net_from_arm <- netmeta(pw) ``` ### Network Visualization ```r library(netmeta) # Network graph netgraph(net, plastic = FALSE, thickness = "number.of.studies", multiarm = TRUE, points = TRUE, cex.points = 3, col = "darkblue") # Improved network graph netgraph(net, seq = "optimal", # Optimal node arrangement plastic = FALSE, thickness = "se.fixed", # Edge thickness by precision number.of.studies = TRUE, # Show number of studies col = "#4477AA", col.points = "#CC6677", cex.points = 4, labels = paste0(trts(net), "\n(n=", n.arms(net), ")")) ``` ## Frequentist NMA with netmeta ### Basic Network Meta-Analysis ```r library(netmeta) # Fit NMA (fixed and random effects) net <- netmeta( TE = TE, seTE = seTE, treat1 = treat1, treat2 = treat2, studlab = study, data = pairwise_data, sm = "MD", fixed = TRUE, random = TRUE, reference.group = "A" ) # Summary summary(net) # Results for specific comparison net$TE.fixed["B", "A"] # Fixed effect B vs A net$TE.random["B", "A"] # Random effects B vs A net$seTE.random["B", "A"] # SE for random effects ``` ### Forest Plot for NMA ```r library(netmeta) # Forest plot: all treatments vs reference forest(net, reference.group = "A", sortvar = TE, smlab = "Mean Difference vs A", drop.reference.group = TRUE, label.left = "Favors A", label.right = "Favors Treatment") # Forest plot with subgroup (by comparison type) forest(net, reference.group = "A", direct = TRUE) # Show direct evidence only ``` ### League Table ```r library(netmeta) # League table (all pairwise comparisons) league <- netleague( net, digits = 2, bracket = "(", separator = " to ", fixed = FALSE # Use random effects ) # Print league table print(league, common = FALSE) # As matrix league$random ``` ### Treatment Rankings ```r library(netmeta) # P-scores (frequentist ranking) netrank(net, small.values = "good") # Rankogram set.seed(123) rank <- rankogram(net, nsim = 1000) plot(rank) # SUCRA-like plot plot(rank, cumulative = TRUE) ``` ## Bayesian NMA with gemtc ### Basic Bayesian NMA ```r library(gemtc) # Prepare data for gemtc (arm-level) network_data <- list( data.ab = data.frame( study = c("S1", "S1", "S2", "S2", "S3", "S3", "S3"), treatment = c("A", "B", "A", "C", "A", "B", "C"), responders = c(15, 22, 12, 18, 20, 28, 24), sampleSize = c(50, 52, 48, 49, 55, 58, 54) ) ) # Create network object network <- mtc.network(data.ab = network_data$data.ab) # Plot network plot(network) # Consistency model model <- mtc.model( network, type = "consistency", likelihood = "binom", link = "logit", linearModel = "random" ) # Run MCMC set.seed(123) result <- mtc.run( model, n.adapt = 5000, n.iter = 20000, thin = 1 ) summary(result) ``` ### Model Diagnostics ```r library(gemtc) library(coda) # Trace plots plot(result) # Gelman-Rubin diagnostic gelman.diag(result$samples) gelman.plot(result$samples) # Effective sample size effectiveSize(result$samples) # Autocorrelation autocorr.plot(result$samples) # Density plots densplot(result$samples) ``` ### Treatment Rankings (Bayesian) ```r library(gemtc) # Rank probabilities ranks <- rank.probability(result) print(ranks) # Plot rank probabilities plot(ranks) # SUCRA sucra <- sucra(ranks) print(sucra) # Cumulative ranking plot plot(ranks, beside = TRUE) ``` ## Bayesian NMA with multinma ### Using multinma Package ```r library(multinma) # Prepare data nma_data <- set_agd_arm( data = arm_data, study = study, trt = treatment, r = events, n = n ) # Network plot plot(nma_data) # Fit Bayesian NMA nma_fit <- nma( nma_data, trt_effects = "random", prior_intercept = normal(scale = 10), prior_trt = normal(scale = 10), prior_het = half_normal(scale = 1) ) # Summary summary(nma_fit) print(nma_fit, pars = "d") # Treatment effects relative_effects(nma_fit, all_contrasts = TRUE) ``` ### Population-Adjusted NMA ```r library(multinma) # With individual patient data (IPD) and aggregate data (AgD) # IPD data ipd_data <- set_ipd( data = ipd_df, study = study, trt = treatment, y = outcome ) # AgD data agd_data <- set_agd_arm( data = agd_df, study = study, trt = treatment, r = events, n = n ) # Combine networks combined_network <- combine_network(ipd_data, agd_data) # Fit with covariate adjustment nma_cov <- nma( combined_network, trt_effects = "random", regression = ~age + sex ) ``` ## Consistency Assessment ### Global Inconsistency Tests ```r library(netmeta) # Design-by-treatment interaction model decomp <- decomp.design(net) print(decomp) # Q statistics decomp$Q.decomp # Overall Q decomposition decomp$Q.het.design # Within-design heterogeneity decomp$Q.inc.detach # Between-design inconsistency # Net heat plot (visual inconsistency) netheat(net) ``` ### Local Inconsistency (Node-Splitting) ```r library(netmeta) # Node-splitting for all comparisons with direct evidence netsplit_result <- netsplit(net) print(netsplit_result) # Forest plot of node-splitting forest(netsplit_result) # Using gemtc for Bayesian node-splitting library(gemtc) # Node-split model nodesplit <- mtc.nodesplit(network, comparisons = NULL) # All comparisons # Run each comparison ns_results <- lapply(nodesplit, function(model) { mtc.run(model, n.adapt = 5000, n.iter = 20000) }) # Summary mtc.nodesplit.comparisons(nodesplit) ``` ### Inconsistency Model ```r library(gemtc) # Unrelated mean effects (inconsistency) model model_ume <- mtc.model( network, type = "ume", likelihood = "binom", link = "logit" ) result_ume <- mtc.run(model_ume, n.adapt = 5000, n.iter = 20000) # Compare DIC summary(result)$DIC # Consistency model summary(result_ume)$DIC # Inconsistency model # Model comparison mtc.deviance(result) ``` ## Heterogeneity Assessment ```r library(netmeta) # Heterogeneity statistics net$tau # Tau (between-study SD) net$tau2 # Tau-squared net$I2 # I-squared net$Q # Q statistic net$df.Q # Degrees of freedom net$pval.Q # P-value for Q # Prediction intervals net$lower.predict # Lower prediction interval net$upper.predict # Upper prediction interval ``` ## Network Meta-Regression ```r library(netmeta) # With study-level covariate net_reg <- netmeta( TE = TE, seTE = seTE, treat1 = treat1, treat2 = treat2, studlab = study, data = pairwise_data, sm = "MD" ) # Meta-regression using netmetareg (requires netmeta >= 2.0) # net_reg <- netmetareg(net, ~year) # Alternative: Use gemtc with covariates library(gemtc) # Add study-level covariate network_cov <- mtc.network( data.ab = network_data$data.ab, studies = data.frame( study = c("S1", "S2", "S3"), year = c(2010, 2015, 2020) ) ) model_reg <- mtc.model( network_cov, type = "regression", regressor = list(coefficient = "shared", variable = "year") ) result_reg <- mtc.run(model_reg, n.adapt = 5000, n.iter = 20000) summary(result_reg) ``` ## Subgroup and Sensitivity Analysis ```r library(netmeta) # Subgroup NMA by risk of bias net_low_rob <- netmeta( TE = TE[rob == "low"], seTE = seTE[rob == "low"], treat1 = treat1[rob == "low"], treat2 = treat2[rob == "low"], studlab = study[rob == "low"], sm = "MD" ) # Compare results comparison_table <- data.frame( Model = c("All studies", "Low RoB only"), Tau = c(net$tau, net_low_rob$tau), Effect_B_vs_A = c(net$TE.random["B", "A"], net_low_rob$TE.random["B", "A"]) ) ``` ## Reporting and Visualization ### PRISMA-NMA Flow Diagram ```r # Recommended reporting items for NMA # 1. Network geometry # 2. Assessment of transitivity # 3. Presentation of results (forest, league table) # 4. Ranking with uncertainty # 5. Assessment of inconsistency # 6. Assessment of heterogeneity
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub