The PTZ Clonic CST outcome has the most data (k = 29, 9 studies) and
is the primary focus of further analyses.
mod <- models_cont[["D1_PTZ_Clonic_CST"]]
pi <- predict(mod)
i2 <- i2_summary(mod)
# Ajan renk kodlaması
drug_full <- ifelse(grepl("Tadalafil", d$M1_Agent_Class), "Tadalafil",
ifelse(grepl("kariin", d$M1_Agent_Class), "Icariin",
"Sildenafil"))
cols <- ifelse(grepl("Tadalafil", d$M1_Agent_Class), "#C62828",
ifelse(grepl("kariin", d$M1_Agent_Class), "#2E7D32", "#1565C0"))
author_short <- sub("(\\S+).*?(\\d{4})$", "\\1 et al. \\2", d$First_Author_Year)
author_short <- gsub("\u0142", "l", author_short)
drug_dose <- paste0(drug_full, " (", d$Dose_mgkg, ")")
studies <- unique(d$Study_ID); row_pos <- numeric(nrow(d)); current <- 0
for (s in rev(studies)) {
idx <- which(d$Study_ID == s)
row_pos[idx] <- (current + 1):(current + length(idx))
current <- current + length(idx) + 1
}
ylim_top <- max(row_pos) + 4; ylim_bot <- -6
total_pde5i <- sum(d$n_PDE5i, na.rm = TRUE)
total_ctrl <- round(sum(d$n_Control_adj, na.rm = TRUE), 1)
par(mar = c(5, 1, 6, 1))
forest(mod, slab = author_short, rows = row_pos,
ylim = c(ylim_bot, ylim_top), xlim = c(-28, 9),
at = c(-8, -6, -4, -2, 0, 2, 4), xlab = "",
header = FALSE, col = cols, border = cols,
pch = 15, cex = 0.85, refline = 0, addpred = TRUE, mlab = "",
ilab = cbind(drug_dose, format(d$n_PDE5i, width=3),
format(round(d$n_Control_adj,1), width=4)),
ilab.xpos = c(-20.0, -13.8, -12.0))
rect(-28, 0.3, 9, 0.8, col = "white", border = NA)
text(-28, ylim_top-0.8, "Study", pos=4, font=2, cex=0.90)
text(-20.0, ylim_top-0.8, "Drug (Dose)", adj=0.5, font=2, cex=0.85)
text(-13.8, ylim_top-0.8, "n\n(PDE5i)", adj=0.5, font=2, cex=0.85)
text(-12.0, ylim_top-0.8, "n\n(Control)*",adj=0.5, font=2, cex=0.85)
text(9, ylim_top-0.8, "SMD [95% CI]", pos=2, font=2, cex=0.90)
abline(h = ylim_top-1.5, lwd=0.6, col="gray40")
abline(h = 0.7, lwd=0.6, col="gray40")
text(-28, -0.5, "Total N:", pos=4, font=2, cex=0.90)
text(-13.8, -0.5, total_pde5i, adj=0.5, font=2, cex=0.90)
text(-12.0, -0.5, total_ctrl, adj=0.5, font=2, cex=0.90)
text(-25, -1.8,
paste0("Pooled SMD = ", round(mod$b,2),
" [", round(mod$ci.lb,2), ", ", round(mod$ci.ub,2), "] ",
"PI [", round(pi$pi.lb,2), ", ", round(pi$pi.ub,2), "] ",
"I\u00B2 = ", i2["Total"], "%"),
pos=4, cex=0.88, font=3)
text(-8, ylim_bot+1.8, "<-- Proconvulsant", adj=1, cex=0.85, font=3, col="gray35")
text( 4, ylim_bot+1.8, "Anticonvulsant -->", adj=0, cex=0.85, font=3, col="gray35")
mtext("SMD (Hedges' g)", side=1, line=2.0, adj=0.65, cex=0.90)
mtext("Effect of PDE5 Inhibitors on PTZ-induced Clonic Seizure Threshold",
side=3, line=3.5, font=2, cex=1.10)
mtext("* n (Control): adjusted for shared control groups (n_original / k comparisons)",
side=1, line=3.8, adj=0, cex=0.70, font=3, col="gray40")
How to read this forest plot
Each square is one comparison (one drug dose in one
study). Squares to the left of the dashed line (0) mean
the drug lowered the seizure threshold (proconvulsant). The
horizontal lines through each square are the 95%
confidence interval — if they cross zero, that comparison alone is not
statistically significant.
The blue diamond at the bottom is the pooled
estimate — the best overall summary across all 29 comparisons.
The dashed lines extending from it show the
prediction interval (PI) — where a new study’s result
would likely fall.
Key numbers:
data.frame(
Metric = c("Pooled SMD", "95% Confidence Interval", "p-value",
"95% Prediction Interval",
"I\u00B2 total", "I\u00B2 between studies", "I\u00B2 within studies"),
Value = c(round(mod$b, 3),
paste0("[", round(mod$ci.lb,3), ", ", round(mod$ci.ub,3), "]"),
round(mod$pval, 4),
paste0("[", round(pi$pi.lb,2), ", ", round(pi$pi.ub,2), "]"),
paste0(i2["Total"], "%"),
paste0(i2["Between"], "%"),
paste0(i2["Within"], "%")),
Interpretation = c(
"Negative = proconvulsant direction",
"Does not include 0: effect is statistically significant",
"p < 0.05: significant at conventional threshold",
"Crosses 0: substantial between-study variability",
"64% of variance is real heterogeneity (not sampling error)",
"Half the heterogeneity comes from between-study differences",
"Half comes from within-study differences (different doses)"
)
) |>
kable(caption = "Table 3. Key numbers from the PTZ Clonic CST meta-analysis.") |>
kable_styling(bootstrap_options = c("striped","hover"), full_width = TRUE)
Table 3. Key numbers from the PTZ Clonic CST meta-analysis.
|
Metric
|
Value
|
Interpretation
|
|
Pooled SMD
|
-0.845
|
Negative = proconvulsant direction
|
|
95% Confidence Interval
|
[-1.605, -0.085]
|
Does not include 0: effect is statistically significant
|
|
p-value
|
0.0305
|
p < 0.05: significant at conventional threshold
|
|
95% Prediction Interval
|
[-3.15, 1.46]
|
Crosses 0: substantial between-study variability
|
|
I² total
|
64%
|
64% of variance is real heterogeneity (not sampling error)
|
|
I² between studies
|
32.9%
|
Half the heterogeneity comes from between-study differences
|
|
I² within studies
|
31.1%
|
Half comes from within-study differences (different doses)
|
What does I² = 64% mean? Studies do not all agree —
there is substantial variability. This is expected in
preclinical meta-analysis (Yang et al. 2022 report typical I² values of
50–90%). The wide prediction interval [−3.15, 1.46] confirms this: while
the average effect is proconvulsant, some future studies may show a
neutral or even anticonvulsant effect (consistent with what we see at
low doses).