
meta-analysis
by matheus-rech
SKILL.md
name: meta-analysis version: 1.0.0 description: Complete meta-analysis generation for neurosurgical outcomes author: NeuroResearch Agent license: MIT
Activation triggers - patterns that activate this skill
triggers:
- pattern: "meta-analysis"
- pattern: "forest plot"
- pattern: "funnel plot"
- pattern: "heterogeneity"
- pattern: "pool.*studies"
- pattern: "synthesize.*data"
- pattern: "publication bias"
- pattern: "subgroup analysis"
- pattern: "sensitivity analysis"
- pattern: "I-squared|I²"
Required MCP servers
requires:
- r-execute
- filesystem
Tools provided by this skill
tools:
-
name: analyze_binary description: Meta-analysis of binary outcomes (OR, RR, RD) script: scripts/binary_meta.R
-
name: analyze_continuous description: Meta-analysis of continuous outcomes (MD, SMD) script: scripts/continuous_meta.R
-
name: analyze_proportion description: Meta-analysis of proportions (single-arm studies) script: scripts/proportion_meta.R
-
name: analyze_survival description: Meta-analysis of hazard ratios script: scripts/survival_meta.R
-
name: generate_forest description: Generate publication-quality forest plot script: scripts/forest_plot.R
-
name: assess_heterogeneity description: Comprehensive heterogeneity assessment script: scripts/heterogeneity.R
-
name: assess_publication_bias description: Publication bias assessment script: scripts/publication_bias.R
-
name: run_subgroup description: Subgroup meta-analysis script: scripts/subgroup.R
-
name: run_sensitivity description: Sensitivity analyses (leave-one-out, influence) script: scripts/sensitivity.R
Data schemas
schemas: binary_input: required: - study: string - events_int: integer - n_int: integer - events_ctrl: integer - n_ctrl: integer optional: - year: integer - subgroup: string
continuous_input: required: - study: string - n_int: integer - mean_int: number - sd_int: number - n_ctrl: integer - mean_ctrl: number - sd_ctrl: number optional: - year: integer - subgroup: string
proportion_input: required: - study: string - events: integer - total: integer optional: - year: integer - subgroup: string
Output specifications
outputs:
- figures/forest_*.png
- figures/funnel_*.png
- results/meta_summary.csv
- results/heterogeneity.txt
- results/publication_bias.txt
Meta-Analysis Skill
Overview
This skill provides comprehensive meta-analysis capabilities for neurosurgical systematic reviews. It supports binary outcomes (mortality, complications), continuous outcomes (scores, measurements), proportions (single-arm success rates), and survival data (hazard ratios).
When to Use
Activate this skill when the user:
- Has extracted data ready for pooling
- Requests forest plots, funnel plots, or heterogeneity assessment
- Needs subgroup or sensitivity analyses
- Asks about publication bias or effect sizes
- Wants to synthesize results from multiple studies
Workflow
1. Data Preparation
Before analysis, ensure data is in the correct format:
# Binary outcomes (2x2 data)
study,year,events_int,n_int,events_ctrl,n_ctrl,subgroup
Smith,2020,10,50,5,50,early
Jones,2021,15,60,8,55,late
# Continuous outcomes
study,year,n_int,mean_int,sd_int,n_ctrl,mean_ctrl,sd_ctrl
Smith,2020,50,25.3,5.2,50,30.1,6.1
# Proportions (single-arm)
study,year,events,total
Smith,2020,42,50
Jones,2021,38,55
2. Main Analysis
For binary outcomes (OR, RR, RD):
Run a meta-analysis of mortality using OR with random effects.
Input: extractions/pooled_data.csv
For continuous outcomes (MD, SMD):
Run a meta-analysis of ODI scores using MD.
Input: extractions/continuous_data.csv
For proportions:
Calculate the pooled proportion of surgical success.
Input: extractions/case_series_data.csv
3. Interpretation Guidelines
Effect Measures
- OR (Odds Ratio): >1 favors control, <1 favors intervention
- RR (Risk Ratio): Same interpretation as OR
- MD (Mean Difference): Actual units, clinically interpretable
- SMD (Standardized Mean Difference): 0.2 small, 0.5 medium, 0.8 large
Heterogeneity (I²)
- 0-25%: Low heterogeneity
- 25-50%: Moderate heterogeneity
- 50-75%: Substantial heterogeneity
-
75%: Considerable heterogeneity
When I² > 50%, consider:
- Exploring sources via subgroup/meta-regression
- Using random-effects model (default)
- Reporting prediction interval
- Conducting sensitivity analyses
Publication Bias
- Funnel plot asymmetry suggests bias
- Egger's test: p < 0.10 indicates asymmetry
- Peters' test: Preferred for binary outcomes
- Trim-and-fill: Estimates adjusted effect
4. Reporting Checklist
For each meta-analysis, generate:
- Forest plot with prediction interval
- Summary statistics (effect, CI, p-value)
- Heterogeneity statistics (I², τ², Q, prediction interval)
- Publication bias assessment (if k ≥ 10)
- Sensitivity analyses
- Subgroup analyses (if pre-specified)
R Code Templates
Binary Outcomes Template
library(meta)
library(metafor)
data <- read.csv("{{INPUT}}")
ma <- metabin(
event.e = events_int,
n.e = n_int,
event.c = events_ctrl,
n.c = n_ctrl,
studlab = paste(study, year),
data = data,
sm = "{{MEASURE}}", # OR, RR, RD
method = "MH", # MH, Inverse, GLMM
random = TRUE,
fixed = FALSE,
prediction = TRUE,
hakn = TRUE # Knapp-Hartung adjustment
)
# Forest plot
png("{{OUTPUT}}/forest_plot.png", width = 1200, height = 800, res = 150)
forest(ma,
sortvar = TE,
prediction = TRUE,
print.tau2 = TRUE,
print.I2 = TRUE,
leftcols = c("studlab", "event.e", "n.e", "event.c", "n.c"),
rightcols = c("effect", "ci", "w.random"))
dev.off()
Heterogeneity Assessment
# Comprehensive heterogeneity assessment
cat("=== HETEROGENEITY ASSESSMENT ===\n\n")
# Statistics
cat(sprintf("I² = %.1f%% [%.1f%%, %.1f%%]\n",
ma$I2*100, ma$lower.I2*100, ma$upper.I2*100))
cat(sprintf("τ² = %.4f (τ = %.4f)\n", ma$tau2, sqrt(ma$tau2)))
cat(sprintf("H² = %.2f\n", ma$H^2))
cat(sprintf("Q = %.2f, df = %d, p = %.4f\n", ma$Q, ma$df.Q, ma$pval.Q))
cat(sprintf("\nPrediction interval: [%.2f, %.2f]\n",
exp(ma$lower.predict), exp(ma$upper.predict)))
# Baujat plot (outlier detection)
png("{{OUTPUT}}/baujat_plot.png", width = 800, height = 600, res = 150)
baujat(ma)
dev.off()
# GOSH plot (if < 15 studies)
if (ma$k <= 15) {
gosh_result <- gosh(ma)
png("{{OUTPUT}}/gosh_plot.png", width = 800, height = 600, res = 150)
plot(gosh_result)
dev.off()
}
Publication Bias Assessment
# Only reliable if k >= 10
if (ma$k >= 10) {
# Funnel plot
png("{{OUTPUT}}/funnel_plot.png", width = 800, height = 600, res = 150)
funnel(ma, studlab = TRUE, cex.studlab = 0.7)
dev.off()
# Contour-enhanced funnel plot
png("{{OUTPUT}}/funnel_contour.png", width = 800, height = 600, res = 150)
funnel(ma, contour = c(0.9, 0.95, 0.99),
col.contour = c("darkgray", "gray", "lightgray"))
legend("topright", c("p < 0.10", "p < 0.05", "p < 0.01"),
fill = c("darkgray", "gray", "lightgray"), bty = "n")
dev.off()
# Statistical tests
cat("\n=== PUBLICATION BIAS TESTS ===\n\n")
# Egger's test (continuous outcomes)
egger <- metabias(ma, method = "Egger")
cat(sprintf("Egger's test: t = %.2f, p = %.4f\n",
egger$statistic, egger$p.value))
# Peters' test (binary outcomes - preferred)
peters <- metabias(ma, method = "Peters")
cat(sprintf("Peters' test: t = %.2f, p = %.4f\n",
peters$statistic, peters$p.value))
# Trim-and-fill
tf <- trimfill(ma)
cat(sprintf("\nTrim-and-fill: %d studies imputed\n", tf$k0))
cat(sprintf("Adjusted estimate: %.2f [%.2f, %.2f]\n",
exp(tf$TE.random), exp(tf$lower.random), exp(tf$upper.random)))
# Funnel with imputed studies
png("{{OUTPUT}}/funnel_trimfill.png", width = 800, height = 600, res = 150)
funnel(tf, studlab = TRUE)
dev.off()
} else {
cat("\nNote: k < 10, publication bias tests unreliable.\n")
cat("Visual inspection of funnel plot only.\n")
}
Sensitivity Analyses
# Leave-one-out analysis
l1o <- metainf(ma, pooled = "random")
png("{{OUTPUT}}/leave_one_out.png", width = 1000, height = 600, res = 150)
forest(l1o)
dev.off()
# Influence diagnostics
inf <- influence(ma)
png("{{OUTPUT}}/influence.png", width = 1000, height = 800, res = 150)
plot(inf)
dev.off()
# Cumulative meta-analysis (by year)
cum <- metacum(ma, sortvar = data$year)
png("{{OUTPUT}}/cumulative.png", width = 1000, height = 600, res = 150)
forest(cum)
dev.off()
# Report influential studies
cat("\n=== INFLUENTIAL STUDIES ===\n\n")
influential <- which(inf$is.infl)
if (length(influential) > 0) {
cat("The following studies are potentially influential:\n")
for (i in influential) {
cat(sprintf(" - %s\n", ma$studlab[i]))
}
} else {
cat("No studies identified as influential.\n")
}
Subgroup Analysis
# Update with subgroup
ma_sub <- update(ma, subgroup = data${{SUBGROUP}})
# Forest plot with subgroups
png("{{OUTPUT}}/forest_subgroup.png", width = 1400, height = 1000, res = 150)
forest(ma_sub,
sortvar = TE,
prediction = TRUE,
subgroup = TRUE,
print.subgroup.labels = TRUE,
subgroup.hetstat = TRUE)
dev.off()
# Test for subgroup differences
cat("\n=== SUBGROUP ANALYSIS ===\n\n")
cat(sprintf("Test for subgroup differences:\n"))
cat(sprintf(" Q = %.2f, df = %d, p = %.4f\n",
ma_sub$Q.b.random, ma_sub$df.Q.b, ma_sub$pval.Q.b.random))
# Within-subgroup heterogeneity
for (sg in unique(data${{SUBGROUP}})) {
ma_sg <- subset(ma_sub, subgroup == sg)
cat(sprintf("\n%s (k = %d):\n", sg, ma_sg$k))
cat(sprintf(" Effect: %.2f [%.2f, %.2f]\n",
exp(ma_sg$TE.random), exp(ma_sg$lower.random), exp(ma_sg$upper.random)))
cat(sprintf(" I² = %.1f%%\n", ma_sg$I2 * 100))
}
Common Issues & Solutions
Missing SDs
If SDs are not reported, estimate from:
- SE: SD = SE × √n
- 95% CI: SD = (upper - lower) × √n / 3.92
- IQR: SD ≈ IQR / 1.35
- Range: SD ≈ Range / 4
Zero Events
Add continuity correction:
metabin(..., incr = 0.5, method.incr = "only0")
Median/IQR Data
Convert using Wan et al. (2014) method:
library(estmeansd)
bc.mean.sd(q1.val = Q1, med.val = median, q3.val = Q3, n = n)
Hazard Ratios
If only HR and CI reported:
log_hr <- log(hr)
se <- (log(ci_upper) - log(ci_lower)) / 3.92
GRADE Integration
After analysis, assess certainty:
- Risk of bias: Overall from RoB assessment
- Inconsistency: Based on I² and prediction interval
- Indirectness: Population, intervention, outcome match
- Imprecision: CI crosses clinical threshold or wide
- Publication bias: Funnel asymmetry, trim-and-fill impact
Generate Summary of Findings table with absolute effects.
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon