关于案例与软件 本教程的医学和心理学研究均为模拟的研究级汇总数据,不对应真实论文、患者或参与者。本页用 base R 展开核心计算,以便看清模型;正式综述应使用经过验证的专业软件,锁定版本与设置,并由另一分析者复核。
本教程沿着真实证据综合的顺序展开:
可回答的问题 → 预注册方案 → 系统检索与筛选 → 偏倚风险 → 可比效应量 → 合成模型 → 异质性 → 稳健性与缺失证据 → 确定性与报告
代码展示的是统计合成部分;它不能代替系统检索、双人筛选、数据核对和偏倚评估。建议先通读概念,再分别完成医学和心理学案例,最后使用检查清单设计自己的分析。
完成本教程后,你应能够:
| 概念 | 核心任务 | 是否一定统计合成 |
|---|---|---|
| 系统综述 | 按预设、透明、可复核的方法检索、筛选、评价并综合证据 | 否 |
| Meta 分析 | 在可辩护的共同问题和统计模型下定量合并研究结果 | 是 |
| 叙述性综述 | 以文字组织文献,方法透明度可有很大差异 | 否 |
一个 Meta 分析可以计算正确却回答错误的问题。例如,把不同疾病、不同干预版本、不同随访期或不同构念的量表合并,精确的平均数也可能没有清晰含义。反之,当临床或方法差异使合并不合理时,高质量系统综述可以不做 Meta 分析。
垃圾进,精确垃圾出 Meta 分析不会把有系统偏倚的研究“平均成无偏真相”。若偏倚方向相似,增加研究数可能让错误结论更精确。研究质量、可比性和缺失证据必须进入解释,而不是只在讨论最后列一句局限。
每一个 forest plot 背后都应有一个明确的 synthesis question:
医学示例的目标是:在 12 项模拟平行随机试验代表的一组可交换场景中,新预防方案相对标准管理对 30 天感染风险的平均 RR。心理学示例的目标是:在 14 项模拟 CBT 试验中,治疗结束时抑郁症状的平均 Hedges’ ;所有量表先统一为“分数越高症状越重”,所以负值有利于 CBT。
在读取研究结果前,方案至少应固定:数据库和灰色文献来源、完整检索式、检索日期、语言和出版状态限制、双人筛选流程、冲突解决方式、主要结局与时间点、效应尺度、合成模型、零事件和缺失 SD 处理、亚组、敏感性分析及偏倚风险工具。
同一研究可能有注册记录、会议摘要、主要论文和多篇二次分析。Meta 分析的单位通常是研究或独立比较,不是 PDF 篇数;重复纳入同一参与者会人为提高精度。多篇报告应先链接为同一研究,再按预设规则抽取。
PRISMA 2020 是系统综述报告指南,不等于预注册。协议可根据主题注册于 PROSPERO、OSF 或其他适用平台;观察性流行病学 Meta 分析还可参考 MOOSE。
令治疗组事件/非事件为 ,对照组为 。风险比在对数尺度上计算:
优势比为 ,风险差为 。三者回答不同问题:
| 尺度 | 零效应值 | 优点 | 限制 |
|---|---|---|---|
| RR | 1 | 队列与试验中较直观;常较稳定 | 仍需基线风险才能理解绝对影响 |
| OR | 1 | 病例对照研究可估;逻辑模型自然输出 | 结局常见时不能称为 RR |
| RD | 0 | 直接表达绝对风险变化 | 常随基线风险明显变化,跨研究异质性可能大 |
分析前必须统一事件方向。“感染”与“无感染”互换会把 RR 变成另一个非简单倒数的量;不能等看到哪个方向显著后再选择结局编码。
单臂零事件使普通 log RR 或 log OR 无定义;两臂都零事件对这些相对尺度不提供直接信息。固定向四格加 0.5 可能在小样本、不平衡分配和罕见事件时引入偏差。应预设并比较适合问题的方法,如 Mantel–Haenszel、广义线性混合模型、beta-binomial 或其他罕见事件方法。
本教程函数不会静默修正:只要四格中任一格为零,就要求预设处理;只有明确设置
correction = TRUE
才对该研究四格加连续性校正,并标记双零事件研究。
zero_demo <- data.frame(
study = c("单臂零事件", "双臂零事件"),
event_t = c(0, 0), total_t = c(50, 50),
event_c = c(3, 0), total_c = c(50, 60)
)
zero_effect <- effect_log_rr(
zero_demo$event_t, zero_demo$total_t,
zero_demo$event_c, zero_demo$total_c,
correction = TRUE
)
knitr::kable(
cbind(zero_demo, zero_effect),
digits = 3,
caption = "显式 0.5 校正的教学示例;双零研究的 log RR 保留为缺失"
)| study | event_t | total_t | event_c | total_c | yi | vi | se | corrected | double_zero |
|---|---|---|---|---|---|---|---|---|---|
| 单臂零事件 | 0 | 50 | 3 | 50 | -1.95 | 2.25 | 1.5 | TRUE | FALSE |
| 双臂零事件 | 0 | 50 | 0 | 60 | NA | NA | NA | TRUE | TRUE |
当研究使用同一量表和单位时,均值差最容易解释:
不同量表测量同一构念时,可用合并组内 SD 标准化:
对小样本 Cohen’s 偏倚作校正。本教程使用一种常见的大样本方差近似;专业软件可能提供不同方差选项,方案中必须记录。
SMD 不是“万能临床单位”。它会受到研究内个体异质性、量表信度、纳入标准和 SD 计算方式影响。只有当量表确实测量相同构念时才应合并;不能仅因为都叫“心理健康评分”就放在一起。
心理学数据的方向审核 抽取表必须记录每个量表的高分含义和是否反向。若一项量表高分代表改善、另一项高分代表症状加重,应在合成前翻转其中一个效应方向。推荐在方案中规定“负值有利于干预”或相反方向,并由第二位分析者核对。
许多 Meta 分析可统一写成:每项研究提供效应估计 及已知或估计的抽样方差 。共同效应模型的权重为 :
权重反映精度,不是研究质量分数。偏倚风险高的大型研究仍可能得到很大逆方差权重,因此偏倚风险不能通过简单乘一个主观“质量权重”解决。
| 模型 | 工作假设 | 汇总量的含义 |
|---|---|---|
| 共同效应(传统 fixed-effect) | 所有研究估计同一个真实效应,差异来自抽样误差 | 该共同效应 |
| 随机效应 | 研究真实效应来自一个分布,观察差异来自真实变异与抽样误差 | 该分布的平均效应 |
随机效应权重为 ,其中 是研究间真实效应方差。随机效应并没有“解决”异质性;它用一个分布模型描述未解释的变异。选择模型应依据问题与预期差异,而不是先做 检验再自动切换。
随机效应并非天然更保守 存在异质性时,随机效应相对提高小研究权重。若小研究因选择性发表或方法问题给出更大效应,随机效应平均值甚至可能离无效值更远。共同效应和随机效应都依赖研究可比性与偏倚假设。
会受研究精度影响:同样的 在更精确研究中可能产生更高 。应同时报告 、预测区间、研究情境和 effect scale,而不是用固定的 25%/50%/75% 标签替代判断。
估计器与平均效应 CI 方法是两个不同选择。HKSJ/Knapp–Hartung 调整平均效应的不确定性,并不估计 。
本教程随机效应平均值使用 modified Knapp–Hartung(mKH):以 t 分布替代正态临界值,并把残差尺度因子限制为至少 1,避免 KH 方差估计小于未调整的模型方差。mKH 可能较保守,尤其研究很少时;方案应说明具体实现。
平均效应 CI 回答平均值位于何处。预测区间尝试描述一项与纳入研究可交换的新研究中真实效应可能位于何处:
本教程公式中的 使用 mKH 调整后的均值方差。这是 Riley/HTS 类常用近似之一,不是唯一标准。研究很少、效应分布非正态或漏斗图不对称时,预测区间可能不稳定;它也不是未来研究“观察到的估计值”区间。
模拟问题是:与标准管理相比,新预防方案是否降低 30 天感染风险?每一行是一项独立平行 RCT,事件均定义为感染,因此 有利于新方案。
stopifnot(
!anyDuplicated(medical_data$study),
all(medical_data$event_t <= medical_data$total_t),
all(medical_data$event_c <= medical_data$total_c),
all(medical_data$total_t > 0),
all(medical_data$total_c > 0)
)
medical_display <- within(medical_data, {
risk_t <- event_t / total_t
risk_c <- event_c / total_c
})
knitr::kable(
medical_display[c("study", "year", "event_t", "total_t", "event_c", "total_c",
"risk_t", "risk_c")],
digits = 3,
col.names = c("研究", "年份", "新方案事件", "新方案总数",
"标准管理事件", "标准管理总数", "新方案风险", "标准管理风险"),
caption = "模拟医学试验的 30 天感染数据"
)| 研究 | 年份 | 新方案事件 | 新方案总数 | 标准管理事件 | 标准管理总数 | 新方案风险 | 标准管理风险 |
|---|---|---|---|---|---|---|---|
| Med-01 | 2012 | 12 | 120 | 20 | 118 | 0.100 | 0.169 |
| Med-02 | 2013 | 14 | 90 | 15 | 92 | 0.156 | 0.163 |
| Med-03 | 2014 | 10 | 180 | 30 | 175 | 0.056 | 0.171 |
| Med-04 | 2015 | 31 | 240 | 29 | 238 | 0.129 | 0.122 |
| Med-05 | 2016 | 20 | 150 | 25 | 148 | 0.133 | 0.169 |
| Med-06 | 2017 | 27 | 320 | 43 | 315 | 0.084 | 0.137 |
| Med-07 | 2018 | 9 | 110 | 16 | 112 | 0.082 | 0.143 |
| Med-08 | 2019 | 29 | 210 | 24 | 205 | 0.138 | 0.117 |
| Med-09 | 2020 | 31 | 400 | 48 | 395 | 0.078 | 0.122 |
| Med-10 | 2021 | 11 | 170 | 25 | 168 | 0.065 | 0.149 |
| Med-11 | 2022 | 20 | 130 | 19 | 132 | 0.154 | 0.144 |
| Med-12 | 2024 | 28 | 260 | 40 | 255 | 0.108 | 0.157 |
这些只是教学数据。真实抽取还应记录随机化单位、结局定义、失访、ITT 分母、聚类或多臂结构、调整估计、偏倚风险和资金来源。
medical_es <- effect_log_rr(
medical_data$event_t, medical_data$total_t,
medical_data$event_c, medical_data$total_c
)
medical_meta <- cbind(medical_data, medical_es)
medical_meta$rr <- exp(medical_meta$yi)
medical_meta$rr_lower <- exp(medical_meta$yi - qnorm(0.975) * medical_meta$se)
medical_meta$rr_upper <- exp(medical_meta$yi + qnorm(0.975) * medical_meta$se)
knitr::kable(
medical_meta[c("study", "rr", "rr_lower", "rr_upper", "se")],
digits = 3,
col.names = c("研究", "RR", "95% CI 下限", "95% CI 上限", "log RR 的 SE"),
caption = "各项医学试验的风险比"
)| 研究 | RR | 95% CI 下限 | 95% CI 上限 | log RR 的 SE |
|---|---|---|---|---|
| Med-01 | 0.590 | 0.302 | 1.152 | 0.341 |
| Med-02 | 0.954 | 0.489 | 1.861 | 0.341 |
| Med-03 | 0.324 | 0.163 | 0.643 | 0.349 |
| Med-04 | 1.060 | 0.660 | 1.702 | 0.242 |
| Med-05 | 0.789 | 0.459 | 1.358 | 0.277 |
| Med-06 | 0.618 | 0.392 | 0.975 | 0.232 |
| Med-07 | 0.573 | 0.264 | 1.241 | 0.394 |
| Med-08 | 1.180 | 0.712 | 1.955 | 0.258 |
| Med-09 | 0.638 | 0.415 | 0.980 | 0.219 |
| Med-10 | 0.435 | 0.221 | 0.855 | 0.345 |
| Med-11 | 1.069 | 0.599 | 1.908 | 0.296 |
| Med-12 | 0.687 | 0.437 | 1.078 | 0.230 |
每项区间表达该研究的抽样不确定性。小研究区间通常更宽,但较大样本不保证偏倚更小。
medical_common <- fit_meta(medical_meta$yi, medical_meta$vi, method = "common")
medical_dl <- fit_meta(medical_meta$yi, medical_meta$vi, method = "DL")
medical_pm <- fit_meta(medical_meta$yi, medical_meta$vi, method = "PM")
medical_reml <- fit_meta(medical_meta$yi, medical_meta$vi, method = "REML")
fit_row_ratio <- function(fit, label) {
data.frame(
模型 = label,
RR = exp(fit$estimate),
CI下限 = exp(fit$lower),
CI上限 = exp(fit$upper),
PI下限 = if (is.finite(fit$pred_lower)) exp(fit$pred_lower) else NA_real_,
PI上限 = if (is.finite(fit$pred_upper)) exp(fit$pred_upper) else NA_real_,
tau平方 = fit$tau2,
check.names = FALSE
)
}
medical_model_table <- rbind(
fit_row_ratio(medical_common, "共同效应 + Wald"),
fit_row_ratio(medical_dl, "随机效应 DL + mKH"),
fit_row_ratio(medical_pm, "随机效应 PM + mKH"),
fit_row_ratio(medical_reml, "随机效应 REML + mKH")
)
knitr::kable(
medical_model_table,
digits = 3,
caption = "医学案例在不同模型与研究间方差估计器下的汇总"
)| 模型 | RR | CI下限 | CI上限 | PI下限 | PI上限 | tau平方 |
|---|---|---|---|---|---|---|
| 共同效应 + Wald | 0.729 | 0.623 | 0.854 | NA | NA | 0.000 |
| 随机效应 DL + mKH | 0.720 | 0.571 | 0.909 | 0.421 | 1.23 | 0.047 |
| 随机效应 PM + mKH | 0.720 | 0.570 | 0.909 | 0.409 | 1.27 | 0.053 |
| 随机效应 REML + mKH | 0.721 | 0.572 | 0.910 | 0.429 | 1.21 | 0.043 |
REML 随机效应平均 RR 约为 0.72,mKH 95% CI 为 0.57 至 0.91。这表示在模型所代表的可交换场景中,平均相对风险较低;它不是“每个医院都会降低相同比例”的承诺。
medical_heterogeneity <- data.frame(
指标 = c("Cochran Q", "Q 自由度", "Q 检验 p 值", "I-squared (%)",
"H-squared", "REML tau-squared", "REML tau"),
数值 = c(
medical_reml$Q, medical_reml$Q_df, medical_reml$Q_p,
medical_reml$I2, medical_reml$H2,
medical_reml$tau2, sqrt(medical_reml$tau2)
)
)
knitr::kable(
medical_heterogeneity,
digits = 3,
caption = "医学案例的异质性统计量(tau 位于 log RR 尺度)"
)| 指标 | 数值 |
|---|---|
| Cochran Q | 17.595 |
| Q 自由度 | 11.000 |
| Q 检验 p 值 | 0.091 |
| I-squared (%) | 37.481 |
| H-squared | 1.600 |
| REML tau-squared | 0.043 |
| REML tau | 0.208 |
约为 37.5%,但不应只贴“中等异质性”标签。更直接的信息是 REML 95% 预测区间:RR 0.43 至 1.21,跨过 1。平均效应与 1 不相容,并不保证相似新场景的真实效应一定有利。
平均 CI 与预测区间并不矛盾:前者量化平均 log RR 的估计精度;后者把研究间真实变异也纳入,回答潜在新场景可能有多不同。
forest_meta(
medical_meta$yi,
medical_meta$vi,
labels = paste(medical_meta$study, medical_meta$year),
fit = medical_reml,
ratio = TRUE,
xlab = "风险比 RR(对数间距)",
pooled_label = "REML 平均 RR",
prediction_label = "95% 预测区间"
)模拟医学试验在 log 坐标上绘制的 RR 森林图。方块大小反映随机效应权重;菱形为 REML 平均效应,红线为预测区间。横轴标签显示 RR。
森林图先用于检查方向、精度、离群结果和可见异质性,再读汇总菱形。方块大小不是样本量本身,也不是研究质量评级。
RR 的实际意义取决于基线风险。下面把平均 RR 应用于纳入试验对照组风险的中位数,只作为一种场景转换:
reference_risk <- median(medical_meta$event_c / medical_meta$total_c)
pooled_rr <- exp(medical_reml$estimate)
treated_risk <- reference_risk * pooled_rr
illustrative_rd <- treated_risk - reference_risk
absolute_translation <- data.frame(
对照参考风险 = reference_risk,
应用平均RR后的风险 = treated_risk,
每1000人的风险差 = 1000 * illustrative_rd,
check.names = FALSE
)
knitr::kable(
absolute_translation,
digits = 3,
caption = "把平均 RR 转换到一个教学性参考风险"
)| 对照参考风险 | 应用平均RR后的风险 | 每1000人的风险差 |
|---|---|---|
| 0.146 | 0.106 | -40.8 |
这不是直接合并 RD,也没有传播参考风险、RR 和异质性的全部不确定性。正式决策应使用目标人群的可信基线风险,并展示多个合理场景。
DL、PM 和 REML 的差异提醒我们:研究数有限时, 不是已知常数。还应逐项排除研究并重新估计 :
medical_loo <- leave_one_out(
medical_meta$yi, medical_meta$vi,
labels = medical_meta$study,
method = "REML"
)
medical_loo$rr <- exp(medical_loo$estimate)
medical_loo$rr_lower <- exp(medical_loo$lower)
medical_loo$rr_upper <- exp(medical_loo$upper)
knitr::kable(
medical_loo[c("omitted", "rr", "rr_lower", "rr_upper", "tau2", "I2")],
digits = 3,
col.names = c("排除研究", "平均 RR", "CI 下限", "CI 上限", "tau-squared", "I-squared (%)"),
caption = "医学案例的 leave-one-out REML 分析"
)| 排除研究 | 平均 RR | CI 下限 | CI 上限 | tau-squared | I-squared (%) |
|---|---|---|---|---|---|
| Med-01 | 0.730 | 0.567 | 0.941 | 0.051 | 41.8 |
| Med-02 | 0.706 | 0.550 | 0.907 | 0.050 | 41.0 |
| Med-03 | 0.763 | 0.623 | 0.934 | 0.014 | 16.0 |
| Med-04 | 0.691 | 0.544 | 0.879 | 0.034 | 32.9 |
| Med-05 | 0.713 | 0.550 | 0.923 | 0.058 | 42.9 |
| Med-06 | 0.732 | 0.565 | 0.949 | 0.055 | 41.2 |
| Med-07 | 0.730 | 0.567 | 0.938 | 0.049 | 41.9 |
| Med-08 | 0.688 | 0.548 | 0.864 | 0.022 | 27.3 |
| Med-09 | 0.730 | 0.562 | 0.948 | 0.058 | 41.7 |
| Med-10 | 0.747 | 0.591 | 0.945 | 0.035 | 34.3 |
| Med-11 | 0.697 | 0.547 | 0.889 | 0.042 | 36.7 |
| Med-12 | 0.723 | 0.556 | 0.939 | 0.061 | 42.9 |
影响性分析是诊断工具,不是删研究算法。若某研究改变结论,应核查人群、设计、数据和偏倚风险,并报告含与不含它的结果;仅因它“让结果不显著”而删除属于结果驱动分析。
模拟研究使用 PHQ-9、BDI-II、HADS-D 和 CES-D。它们的单位和范围不同,因此全部 14 项研究不能用原始 MD 合并。我们假设这些量表在此问题中足够接近地测量同一抑郁症状构念,并已统一为高分更差;负 有利于 CBT。
stopifnot(
!anyDuplicated(psychology_data$study),
all(psychology_data$n_t > 1), all(psychology_data$n_c > 1),
all(psychology_data$sd_t > 0), all(psychology_data$sd_c > 0)
)
knitr::kable(
psychology_data,
digits = 2,
col.names = c("研究", "量表", "CBT n", "CBT 均值", "CBT SD",
"对照 n", "对照均值", "对照 SD", "治疗节数", "形式"),
caption = "模拟心理学试验的治疗结束时抑郁量表数据"
)| 研究 | 量表 | CBT n | CBT 均值 | CBT SD | 对照 n | 对照均值 | 对照 SD | 治疗节数 | 形式 |
|---|---|---|---|---|---|---|---|---|---|
| Psy-01 | PHQ-9 | 70 | 11.5 | 5.1 | 68 | 14.5 | 5.0 | 10 | Individual |
| Psy-02 | BDI-II | 55 | 25.4 | 8.2 | 57 | 27.0 | 8.0 | 6 | Group |
| Psy-03 | HADS-D | 90 | 10.4 | 4.0 | 88 | 12.0 | 4.2 | 8 | Individual |
| Psy-04 | CES-D | 120 | 25.5 | 9.5 | 118 | 25.0 | 9.2 | 4 | Group |
| Psy-05 | PHQ-9 | 48 | 11.0 | 4.8 | 50 | 15.0 | 5.1 | 8 | Individual |
| Psy-06 | BDI-II | 75 | 23.7 | 7.7 | 74 | 26.0 | 7.9 | 10 | Group |
| Psy-07 | HADS-D | 130 | 9.5 | 3.8 | 128 | 11.5 | 4.0 | 6 | Individual |
| Psy-08 | CES-D | 62 | 27.0 | 10.2 | 65 | 28.0 | 9.8 | 4 | Group |
| Psy-09 | PHQ-9 | 85 | 10.4 | 5.3 | 82 | 14.0 | 5.0 | 12 | Individual |
| Psy-10 | BDI-II | 110 | 22.5 | 8.0 | 108 | 24.5 | 8.3 | 6 | Group |
| Psy-11 | HADS-D | 58 | 10.7 | 4.1 | 60 | 12.5 | 4.0 | 8 | Individual |
| Psy-12 | CES-D | 140 | 27.9 | 9.4 | 136 | 27.0 | 9.6 | 10 | Group |
| Psy-13 | PHQ-9 | 95 | 12.7 | 4.9 | 92 | 15.5 | 5.2 | 10 | Individual |
| Psy-14 | BDI-II | 72 | 22.7 | 7.9 | 70 | 25.5 | 8.1 | 8 | Group |
真实综述还必须确认诊断标准、对照类型、治疗师训练、盲法可行性、依从性、量表版本和随访时点。等待名单与主动心理对照通常不能无条件视为同一 comparator。
psych_es <- effect_hedges_g(
psychology_data$n_t, psychology_data$mean_t, psychology_data$sd_t,
psychology_data$n_c, psychology_data$mean_c, psychology_data$sd_c
)
psych_meta <- cbind(psychology_data, psych_es)
psych_meta$g_lower <- psych_meta$yi - qnorm(0.975) * psych_meta$se
psych_meta$g_upper <- psych_meta$yi + qnorm(0.975) * psych_meta$se
psych_reml <- fit_meta(psych_meta$yi, psych_meta$vi, method = "REML")
psych_common <- fit_meta(psych_meta$yi, psych_meta$vi, method = "common")
knitr::kable(
psych_meta[c("study", "scale", "yi", "g_lower", "g_upper")],
digits = 3,
col.names = c("研究", "量表", "Hedges g", "95% CI 下限", "95% CI 上限"),
caption = "每项心理学试验的标准化均值差"
)| 研究 | 量表 | Hedges g | 95% CI 下限 | 95% CI 上限 |
|---|---|---|---|---|
| Psy-01 | PHQ-9 | -0.591 | -0.932 | -0.250 |
| Psy-02 | BDI-II | -0.196 | -0.568 | 0.175 |
| Psy-03 | HADS-D | -0.389 | -0.685 | -0.092 |
| Psy-04 | CES-D | 0.053 | -0.201 | 0.307 |
| Psy-05 | PHQ-9 | -0.801 | -1.212 | -0.389 |
| Psy-06 | BDI-II | -0.293 | -0.616 | 0.029 |
| Psy-07 | HADS-D | -0.511 | -0.759 | -0.263 |
| Psy-08 | CES-D | -0.099 | -0.448 | 0.249 |
| Psy-09 | PHQ-9 | -0.695 | -1.008 | -0.383 |
| Psy-10 | BDI-II | -0.245 | -0.511 | 0.022 |
| Psy-11 | HADS-D | -0.442 | -0.807 | -0.076 |
| Psy-12 | CES-D | 0.094 | -0.142 | 0.331 |
| Psy-13 | PHQ-9 | -0.552 | -0.844 | -0.260 |
| Psy-14 | BDI-II | -0.348 | -0.680 | -0.017 |
psych_results <- rbind(
data.frame(
模型 = "共同效应 + Wald", g = psych_common$estimate,
CI下限 = psych_common$lower, CI上限 = psych_common$upper,
PI下限 = NA, PI上限 = NA, tau平方 = 0
),
data.frame(
模型 = "随机效应 REML + mKH", g = psych_reml$estimate,
CI下限 = psych_reml$lower, CI上限 = psych_reml$upper,
PI下限 = psych_reml$pred_lower, PI上限 = psych_reml$pred_upper,
tau平方 = psych_reml$tau2
)
)
knitr::kable(
psych_results,
digits = 3,
caption = "心理学案例的共同效应与随机效应结果"
)| 模型 | g | CI下限 | CI上限 | PI下限 | PI上限 | tau平方 |
|---|---|---|---|---|---|---|
| 共同效应 + Wald | -0.317 | -0.398 | -0.236 | NA | NA | 0.000 |
| 随机效应 REML + mKH | -0.345 | -0.501 | -0.188 | -0.848 | 0.158 | 0.048 |
随机效应平均 为 -0.34(mKH 95% CI -0.50 至 -0.19)。负方向平均有利于 CBT,但这不是 PHQ-9 分数下降多少分,也不应仅按 0.2/0.5/0.8 的固定经验阈值决定临床意义。
psych_heterogeneity <- data.frame(
Q = psych_reml$Q,
Q_df = psych_reml$Q_df,
Q_p = psych_reml$Q_p,
I2_percent = psych_reml$I2,
tau2 = psych_reml$tau2,
tau = sqrt(psych_reml$tau2),
prediction_lower = psych_reml$pred_lower,
prediction_upper = psych_reml$pred_upper,
check.names = FALSE
)
knitr::kable(
psych_heterogeneity,
digits = 3,
col.names = c("Q", "df", "Q p 值", "I-squared (%)", "tau-squared",
"tau", "PI 下限", "PI 上限"),
caption = "心理学案例的异质性与预测区间"
)| Q | df | Q p 值 | I-squared (%) | tau-squared | tau | PI 下限 | PI 上限 |
|---|---|---|---|---|---|---|---|
| 41 | 13 | 0 | 68.3 | 0.048 | 0.219 | -0.848 | 0.158 |
预测区间约为 -0.85 至 0.16,跨过 0。即使平均效应的 CI 未跨 0,某些相似场景的真实效应仍可能接近无效或方向不同。可能原因包括对照强度、治疗形式、样本严重程度、量表、治疗师和偏倚风险,但本数据不能自动识别原因。
forest_meta(
psych_meta$yi,
psych_meta$vi,
labels = paste(psych_meta$study, psych_meta$scale),
fit = psych_reml,
ratio = FALSE,
xlab = "Hedges' g(负值有利于 CBT)",
pooled_label = "REML 平均 g",
prediction_label = "95% 预测区间"
)模拟心理学 CBT 试验的 Hedges’ g 森林图。负值有利于 CBT;菱形为 REML 平均效应,红线为预测区间。
四项 PHQ-9 研究可以用 MD 合成,因为量表和方向一致:
phq <- subset(psychology_data, scale == "PHQ-9")
phq_es <- effect_md(phq$n_t, phq$mean_t, phq$sd_t,
phq$n_c, phq$mean_c, phq$sd_c)
phq_fit <- fit_meta(phq_es$yi, phq_es$vi, method = "REML")
data.frame(
研究数 = phq_fit$k,
平均MD = phq_fit$estimate,
CI下限 = phq_fit$lower,
CI上限 = phq_fit$upper,
tau平方 = phq_fit$tau2,
check.names = FALSE
) |>
knitr::kable(
digits = 3,
caption = "仅 PHQ-9 研究的随机效应均值差(CBT − 对照,单位为 PHQ-9 分)"
)| 研究数 | 平均MD | CI下限 | CI上限 | tau平方 |
|---|---|---|---|---|
| 4 | -3.27 | -4.6 | -1.95 | 0 |
MD 更接近临床解释,但这里只代表 PHQ-9 子集。不能把它与全部量表的 当成同一 estimand;也不应把治疗后分数 SMD 与变化分数 SMD 随意混合,除非预设的方法和相关性假设支持。
下面比较个体 CBT 与团体 CBT。先分别汇总只是描述;亚组差异应通过包含组别指示变量的 Meta 回归直接检验,而不是比较“一组显著、另一组不显著”。
format_levels <- levels(psych_meta$format)
psych_subgroup <- do.call(rbind, lapply(format_levels, function(level) {
take <- psych_meta$format == level
fit <- fit_meta(psych_meta$yi[take], psych_meta$vi[take], method = "REML")
data.frame(
形式 = level, 研究数 = sum(take), 平均g = fit$estimate,
CI下限 = fit$lower, CI上限 = fit$upper, tau平方 = fit$tau2
)
}))
format_dummy <- as.numeric(psych_meta$format == "Individual")
X_format <- cbind(`(Intercept)` = 1, Individual_vs_Group = format_dummy)
format_model <- fit_meta(
psych_meta$yi, psych_meta$vi,
method = "REML", X = X_format
)
knitr::kable(psych_subgroup, digits = 3, caption = "按 CBT 形式分层的描述性合成")| 形式 | 研究数 | 平均g | CI下限 | CI上限 | tau平方 |
|---|---|---|---|---|---|
| Group | 7 | -0.126 | -0.301 | 0.049 | 0.013 |
| Individual | 7 | -0.551 | -0.698 | -0.403 | 0.000 |
| term | estimate | se | lower | upper | statistic | p |
|---|---|---|---|---|---|---|
| (Intercept) | -0.118 | 0.062 | -0.252 | 0.016 | -1.92 | 0.079 |
| Individual_vs_Group | -0.435 | 0.089 | -0.630 | -0.240 | -4.86 | 0.000 |
这里 Individual_vs_Group 系数及其 p
值就是两个亚组平均效应差异的直接检验。若 moderator
有三个或更多水平,应使用全部虚拟变量的 omnibus F/Wald
检验,而不能挑一个系数。该研究层比较即使很精确,也可能被人群、对照强度、治疗节数或偏倚风险混杂,不能解释为把同一患者从团体
CBT 改为个体 CBT 的因果效应。
sessions_centered <- psych_meta$sessions - mean(psych_meta$sessions)
X_sessions <- cbind(`(Intercept)` = 1, sessions_centered = sessions_centered)
sessions_model <- fit_meta(
psych_meta$yi, psych_meta$vi,
method = "REML", X = X_sessions
)
knitr::kable(
sessions_model$coefficients,
digits = 3,
caption = "治疗节数的探索性随机效应 Meta 回归"
)| term | estimate | se | lower | upper | statistic | p |
|---|---|---|---|---|---|---|
| (Intercept) | -0.344 | 0.068 | -0.493 | -0.195 | -5.04 | 0.000 |
| sessions_centered | -0.051 | 0.029 | -0.114 | 0.012 | -1.75 | 0.105 |
斜率描述研究层面每多一节治疗与平均 的关联,并不是个体剂量反应。14 项研究只支持非常有限的 moderator 探索;“每个系数至少约 10 项研究”至多是警示下限,不是充分保证。多重尝试 moderator 会制造偶然发现。
漏斗图绘制效应估计与标准误。若只有抽样误差、模型适当且没有大小相关效应,较精确研究通常聚集在顶部,较小研究在底部更分散。
模拟心理学试验的漏斗图。虚线为 REML 平均效应及其 95% 伪界限;不对称不等同于发表偏倚。
漏斗图不对称可能来自发表或选择性报告,也可能来自真实异质性、小研究实施质量、效应尺度与基线风险关系、异常研究或偶然性。对称也不能证明没有缺失结果。
psych_egger <- egger_test(psych_meta$yi, psych_meta$vi)
knitr::kable(
psych_egger,
digits = 3,
caption = "心理学案例的 Egger 回归截距检验"
)| intercept | se | t | df | p |
|---|---|---|---|---|
| -5.26 | 2.69 | -1.95 | 12 | 0.075 |
Egger 检验通常不应在少于约 10 项独立研究时被强调;即使研究更多,它也是小研究效应检验,不是“发表偏倚检验”。存在异质性时其解释更复杂。Trim-and-fill 也不是找回真实缺失研究的可靠修复,应至多作为强假设下的敏感性分析。
心理学研究常报告多个量表、多个随访、多个干预组和多个亚组。医学试验可能共享一个对照组。把这些相关效应当成独立研究会重复计算参与者并低估标准误。
| 结构 | 相关性来源 | 合理方向 |
|---|---|---|
| 同一研究多个结局 | 同一参与者完成多个量表 | 预设一个主要结局;或多变量/多层 Meta 分析 |
| 多个时间点 | 同一参与者重复测量 | 预设主要时间点;或显式建模时间内相关性 |
| 多臂试验共享对照 | 对照参与者被用于多个比较 | 合并相关干预臂、拆分对照或使用多变量方法 |
| 聚类随机试验 | 同一集群内参与者相关 | 使用已校正的效应/SE,或按 ICC 调整有效样本量 |
| 同一队列多篇论文 | 参与者重复 | 链接报告,按研究 ID 去重 |
正式分析可使用多变量或多层 Meta 分析,或按研究聚类并带小样本修正的稳健方差估计。当前项目不安装相应扩展包,因此本页不以错误的独立性近似演示这些复杂模型。
随机试验可按随机化过程、偏离干预、缺失结局、结局测量和选择性报告等领域评价;观察性研究还需深入考虑混杂和选择。简单把多个领域相加成“质量分数”会隐藏致命问题,且不适合作为机械逆方差修正。
建议把偏倚判断用于:解释方向与大小;预设排除高风险研究的敏感性分析;比较低风险证据;解释异质性;评价证据确定性。排除规则必须在看汇总结果前确定。
在提取结果前写明:
纳入 12 项模拟平行随机试验,共 4733 名参与者。以感染为事件,REML 随机效应模型及 modified Knapp–Hartung 推断得到平均 RR 0.72(95% CI 0.57–0.91)。研究间方差 (log RR 尺度),;95% 预测区间为 0.43–1.21。平均结果提示相对风险降低,但预测区间跨过 1,故效应不应被假定为在所有相似场景中方向一致。所有数据为模拟结果,未进行真实偏倚风险或证据确定性评估。
纳入 14 项模拟 CBT 试验,共 2406 名参与者。统一量表方向后,REML 随机效应模型及 modified Knapp–Hartung 推断得到治疗结束时平均 Hedges’ (95% CI -0.50 至 -0.19;负值有利于 CBT)。,,95% 预测区间为 -0.85 至 0.16。平均症状差异有利于 CBT,但研究间差异较大,预测区间包含无效值,且 SMD 不对应单一量表的临床单位。
报告应使用适用的 PRISMA 2020 checklist 与 flow diagram,并说明每次 synthesis 的纳入研究、模型、效应尺度、 估计器、CI 方法、异质性指标、软件命令和敏感性分析。观察性研究综述可同时参考 MOOSE。
保存检索结果、去重记录、筛选决定、排除理由、数据字典、原始抽取、清洗日志、分析数据、脚本和软件环境。最好由第二位分析者从原始抽取表独立复算主要结果。
| 错误做法 | 为什么有问题 | 更合适的做法 |
|---|---|---|
| “做了 Meta 分析”就称系统综述 | 统计合成不等于系统方法 | 报告完整检索、筛选、偏倚和协议 |
| 按 的 p 值选择 fixed 或 random | 检验效能依赖研究数且两模型问题不同 | 依据 estimand 与临床差异预设模型 |
| 把 写成“60% 研究有异质性” | 不是研究比例 | 联合解释 、PI、尺度与场景 |
| 随机效应称为“已控制异质性” | 未解释差异仍然存在 | 探索原因并报告预测区间 |
| 把 OR 当 RR | 结局常见时差异可明显 | 按设计选尺度并准确命名 |
| 所有零格都自动加 0.5 | 可能产生偏差且双零信息不同 | 预设罕见事件方法并做敏感性分析 |
| 不同量表直接合并 MD | 单位不可比 | 同一构念时用 SMD,或按量表分开 |
| 忘记翻转量表方向 | 有利与有害效应相互抵消 | 保存方向字段并双人核查 |
| 每个量表和时间点都当独立研究 | 重复计算参与者,SE 过小 | 预设选择规则或使用依赖效应模型 |
| 一亚组显著、另一亚组不显著就称有差异 | 显著性差异不是效应差异检验 | 直接检验 subgroup × effect 交互 |
| Meta 回归斜率解释为个体因果效应 | 研究层生态谬误与混杂 | 写成探索性研究层关联 |
| 漏斗图不对称就断言发表偏倚 | 原因不唯一 | 结合注册、方案、异质性与选择机制 |
| 删除让结果变化的研究 | 结果驱动,破坏目标 | 核查、透明报告并保留主分析 |
| 只报告 pooled p 值 | 无大小、精度或可迁移性 | 报告效应、CI、、PI 和偏倚 |
五项研究都报告“焦虑”,但分别研究术前短期紧张、广泛性焦虑障碍和考试焦虑,干预和时间点也不同。能否因为都可转成 SMD 就直接合并?
检验 ,研究者因此选择共同效应模型。这个理由充分吗?
随机效应平均 RR 的 95% CI 为 0.70–0.88,而预测区间为 0.50–1.25。如何解释?
三项抑郁研究中两项量表高分更差,一项量表高分更好。直接计算“干预减对照”的 会发生什么?
一项小型安全性试验两组均无死亡。它对普通 log RR 合成提供什么信息?
成人研究 pooled ,青少年研究 pooled 。能否说年龄组修改疗效?
| 量 | 计算或含义 | 零效应值 |
|---|---|---|
| log RR | 0(RR 为 1) | |
| log OR | 0(OR 为 1) | |
| RD | 0 | |
| MD | 0 | |
| Hedges’ | 小样本校正的标准化均值差 | 0 |
| 共同效应权重 | — | |
| 随机效应权重 | — | |
| 观察不一致的相对比例指标 | 0% | |
| 模型中的研究间真实效应方差 | 0 |
## R version 4.6.1 (2026-06-24)
## Platform: aarch64-apple-darwin23
## Running under: macOS Tahoe 26.5.1
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
##
## locale:
## [1] C.UTF-8/C.UTF-8/C.UTF-8/C/C.UTF-8/C.UTF-8
##
## time zone: America/Edmonton
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.39 R6_2.6.1 fastmap_1.2.0 xfun_0.60 lattice_0.22-9
## [6] cachem_1.1.0 knitr_1.51 htmltools_0.5.9 rmarkdown_2.31 stats4_4.6.1
## [11] lifecycle_1.0.5 cli_3.6.6 grid_4.6.1 sass_0.4.10 jquerylib_0.1.4
## [16] compiler_4.6.1 tools_4.6.1 nlme_3.1-169 evaluate_1.0.5 bslib_0.12.0
## [21] yaml_2.3.12 rlang_1.3.0 jsonlite_2.0.0