☰
公共卫生观察性数据因果推断实战:从反事实框架到倾向性评分
2026/10/7 3:52:59 网站建设 项目流程

说起来有点意思,我最早接触“因果推断”并不是因为追什么方法学热点,而是被一个临床问题逼的。那时候手里握着一批电子病历数据,老板想知道某个新型降糖药是不是比老药更能降低心梗风险。逻辑很简单:两组病人,一组吃新药,一组吃老药,比一比心梗发生率不就行了?结果一做生存分析,新药组的心梗率反而更高。后来才反应过来,开新药的那帮人往往病情更重、合并症更多,基线就不齐。那一刻我就明白,公共卫生里真正难的不是“算出个结果”,而是搞清楚“这个结果能不能当因果用”。

这篇文章我想认真聊聊公共卫生领域的因果实践。不扯太多数学证明,就从实际做项目的角度,讲讲在观察性数据里怎么逼近因果效应、有哪些趁手的工具、核心步骤怎么落地、以及我踩过哪些坑。适合刚接触因果推断的临床研究者、流行病学研究生,还有那些手里有回顾性数据但不知道该怎么“挖”出一篇高质量文章的同行。

1. 从相关到因果:公共卫生决策绕不开的一道坎

1.1 为什么公卫研究必须较真“因果”

很多人觉得公共卫生研究嘛,不就是找关联。哪个指标高了、哪个行为多了,跟疾病有没有关系,做个回归调几个协变量,完事。但公共卫生所有防病治病措施,本质上都默认了一条因果链:干预A会改变健康结局Y。如果你给的是“相关”证据,政策制定者凭什么花钱、花人力去推一项干预?

举个我常用的例子:观察性研究经常发现,喝咖啡的人全因死亡率更低。但如果因为这个就号召全民喝咖啡,风险很大。因为喝咖啡的人可能本身社会经济地位更高、运动更多、体检更勤,这些才是真正保命的因素。你需要回答的不是“喝咖啡的人死得少”,而是“如果让一个不喝咖啡的人开始喝咖啡,他的死亡风险会不会真的下降”——这才是反事实意义上的因果问题。

公共卫生领域对因果证据的需求是刚性的。无论是评估疫苗效果、判断空气污染的健康效应、比较两种治疗方案的优劣,还是制定筛查指南,决策者需要知道的是“改变某个暴露会带来什么后果”,而不是“某个暴露和结局有关联”。这就逼着研究者必须掌握一套超越普通回归的因果分析语言。

1.2 反事实框架:把看不见的对照补出来

因果推断的底层逻辑是二十世纪统计学家提出的反事实框架(Rubin Causal Model)。核心思想很朴素:某个人在“吃药”这个状态下有个潜在结局Y(1),在“不吃药”状态下有个潜在结局Y(0),真正的因果效应是Y(1) - Y(0)。问题在于,一个人在同一时刻只能处于一种状态,你永远只能观测到其中一个潜在结局。

这时候就有两个选择:要么做随机对照试验(RCT),用随机化保证两组在平均意义上除了暴露外没有系统性差异,让未观测的那个结局可以被对方组的观测结局替代;要么用观察性数据,通过统计手段“人为制造”一个可比的对照组,模拟随机化的效果。公共卫生的因果实践,大量精力都花在第二种选择上。

这里有三条假设是观察性因果分析的地基,必须刻在脑子里:

  • 一致性假设:个体接受的暴露必须是明确定义的,不能出现“吃这个药”有不同版本。就像研究降压药,不能把国产仿制药和原研药混为一谈,否则效应定义就是模糊的。
  • 可忽略性假设(无未测混杂):所有影响结局的混杂因素都被测量到了,且在组间平衡。这是观察性研究最脆弱的一环,也是倾向性评分、加权等方法能成立的前提。
  • 正值假设(重叠假设):每一个个体都有一定概率接受任一水平的暴露。如果某个亚组100%都吃新药,那就找不到对照,这部分人群根本没法比较。

我个人的体会是,很多分析翻车都不是因为统计模型不够花哨,而是这三个假设在数据层面根本没满足。开始跑代码之前,先逐条检验这三条,能省下后面一大半返工时间。

1.3 有向无环图:先想清楚逻辑再碰数据

在动手建模前,我非常建议大家画一张有向无环图(DAG)。它解决的是“哪些变量该调整、哪些不该调整”的问题。DAG的规则很直观:箭头表示因果方向,比如“年龄→高血压→心梗”。有了这张图,你可以判断一个变量是混杂因素、中介变量还是对撞变量。

重点是识别对撞变量。对撞变量的特点是多个原因指向它,比如“住院”同时被“疾病严重程度”和“交通事故”指向。如果错误地把对撞变量放入回归模型,反而会打开一条虚假的关联路径,制造出一个本来不存在的相关性,这在实际公卫数据里是最容易踩的暗坑。

DAG还有很多衍生概念,比如最小充分调整集。在R里有dagitty包,画好图后可以直接算出最小调整集,意思是“你最少调整哪几个变量就能把混杂控制住”。我自己的习惯是:先画DAG、再算调整集、最后才写回归公式,顺序不能反。画DAG的过程也是逼自己把领域知识外显化的过程,非常值得花时间。

2. 核心方法选型:不同数据场景挑什么武器

2.1 方法选型先看设计逻辑而非名气

很多初学者容易陷入“追求高级方法”的误区,总觉得断点回归、工具变量比倾向性评分高级。但方法好不好,取决于你的数据生成机制和研究问题。公共卫生领域的主流因果方法基本可以分为两类,一类是“设计型方法”,通过利用某种自然实验或外生冲击来识别因果,比如断点回归、双重差分、工具变量;另一类是“模型型方法”,试图通过统计建模来消除混杂,比如倾向性评分匹配/加权、G方法、多重插补。

设计型方法的优势是识别假设相对少、更接近RCT逻辑,但适用条件苛刻。比如断点回归要求暴露分配在某条阈值处发生突变,像“以70岁为界决定是否接种某疫苗”;双重差分要求处理组和对照组满足平行趋势假设。模型型方法适用范围广,但对“无未测混杂”的依赖很强,一旦有重要的混杂变量没测量,结果再漂亮也白搭。

我自己选型的经验是:先问数据里有没有天然的“外生变动”。有,优先考虑设计型方法;没有,再老老实实做倾向性评分或G计算,并通过多种敏感性分析来佐证结论。

2.2 倾向性评分:观察性研究最常用的地基

倾向性评分(Propensity Score,PS)是 Rosenbaum 和 Rubin 在1983年提出的概念,定义为“给定一组协变量X的条件下,个体接受暴露E的概率”,即P(E=1|X)。它的核心价值在于:把高维协变量压缩成一维评分,只要两组在不同评分区间上的协变量分布足够接近,就相当于在模拟随机化。

实操中PS有四种用法:匹配、分层、逆概率加权(IPTW)、协变量调整。其中IPTW的思路最容易理解,就是让每个人“代表”他自己以及和他特征相似、但暴露状态相反的“未观测替身”,通过加权构造一个人工的随机化样本。我自己最常用的是PS匹配+IPTW交叉验证,如果两种方法给出的效应估计方向一致,心里就踏实很多。

在公共卫生领域用PS,变量选择是门学问。建议把混杂因素分成三类:一是已知的强危险因素(如年龄、性别、并发症),二是与暴露强相关的因素,三是与结局相关的因素。核心原则是:只调整“既影响暴露又影响结局”的混杂,不要调整中介变量(比如研究二甲双胍对心血管的影响时,糖化血红蛋白是中介,调了就相当于抹掉了药物的部分效果)。这一点很多新手会搞错,导致效应被严重低估。

PS分析完成后,第一件事不是看效应量,而是检查两组协变量是否实现了平衡。常用指标是标准化均数差(SMD),一般以绝对值小于0.1为可接受。我见过不少人匹配完不看SMD直接汇报HR,结果基线根本没平衡,等于白做。

2.3 工具变量与孟德尔随机化:应对不可测混杂的利刃

公共卫生数据里有很多混杂是测不到的,比如社会经济地位、生活方式、依从性、健康意识。这些变量很难靠调整协变量解决,这时候可以尝试工具变量(Instrumental Variable, IV)方法。

工具变量需要满足三条核心假设:第一,与暴露强相关(相关性假设);第二,与结局的关系必须完全通过暴露(排他性假设);第三,不与被测或未测混杂相关(独立性假设)。找到满足这三条的工具变量很难,但遗传流行病学给了个很好的思路——孟德尔随机化(Mendelian Randomization, MR),用基因型作为暴露的工具变量。

MR背后的逻辑是:基因型在受孕时随机分配(类似自然界的随机化),与生活方式等后天混杂通常不相关,却决定了某些中间表型(比如低密度脂蛋白胆固醇水平)。因此,如果某个基因位点影响LDL-C水平,且该位点与冠心病风险相关,就能推断LDL-C与冠心病的因果关系。

用MR时有两个最常见的坑:一是弱工具变量,一般用F统计量检验,F<10说明工具变量与暴露的关联太弱,结果不可靠;二是水平多效性,也就是基因位点可能通过其他通路影响结局,这个需要做MR-Egger、加权中位数等敏感性分析来检验。我在实际项目中,MR更适合做一个“验证性分析”,验证传统观察性研究的结论是否可能被不可测混杂颠覆。

2.4 断点回归与双重差分:利用自然实验做因果评估

公共卫生政策评估中,最常用的两个设计型方法是断点回归(RDD)和双重差分(DID)。它们都利用“某种规则或时间节点导致的暴露变化”来识别因果。

RDD的思路是:如果暴露分配取决于某个连续变量是否超过阈值,那么在阈值附近的小邻域内,个体特征几乎是随机分布的,唯一系统不同的是接受暴露的概率突然跳变。比如有研究发现,65岁是很多国家启动某种免费筛查或接种的年龄门槛,比较65岁前后人群的健康结局,就能评估政策效果。RDD的分析重点是带宽选择和数据驱动的最优带宽算法,核心假设是结局-驱动变量曲线在阈值处是连续的。

DID则适用于“政策在某个时间点覆盖某组人群”的场景。比如某省上线了一项慢病管理新政策,拿该省做处理组、邻省做对照组,比较政策前后两组结局变化量的差值。DID的关键假设是平行趋势:如果政策不发生,处理组和对照组的结局变化趋势应该相同。实操中可以通过画事件研究图来检验政策实施前各期的组间差异是否不显著。

这两种方法对数据要求很高,需要精确的驱动变量/时间信息,样本量要足够支撑阈值邻域或组内对比。但它们的因果解释力远强于只看回归系数,如果数据条件允许,是非常值得优先考虑的方案。

为了直观对比,我把这些主流方法放在一张表里:

方法核心识别假设适用场景主要局限
RCT随机化、依从性药物/干预效果确证成本高、外推有限
倾向性评分无未测混杂、正值假设观察性队列、停药效应依赖已测混杂变量
工具变量/MR排他性、独立性、相关性暴露-结局因果验证多效性、弱IV
断点回归阈值处连续性政策/制度阈值效应仅局部效应
双重差分平行趋势政策前后组间对比需要合适对照

3. 实操过程:跑通一个完整的因果分析项目

3.1 从临床问题到因果问题的转化

整个因果分析的第一步不是下载数据,而是把临床问题翻译成因果问题。我习惯用PICOT框架做这一步:P是人群(比如2型糖尿病合并肥胖患者),I是暴露或干预(比如使用GLP-1受体激动剂),C是对照(比如使用DPP-4抑制剂),O是结局(比如5年主要不良心血管事件),T是时间窗。

翻译成因果问题后,还需要明确目标效应。是ATE(全人群平均处理效应),还是ATT(处理组的处理效应)?如果是药物监管视角,一般关注ATE;如果是临床决策视角,可能更关心“实际用了新药这批人”的效果,也就是ATT。这两种效应需要不同的加权或匹配策略,别搞混。

接着,我会拉一个领域知识团队开会画DAG,包括临床医生、流行病学方法学家、统计师。DAG上有几个关键判断要达成一致:哪些是最小调整集、哪些是中介、哪些是工具变量不该调整、有没有对撞变量混在变量清单里。这一步如果讨论不充分,后面统计做得再精致都站不住。

3.2 数据处理与倾向性评分实操

数据清洗是公卫分析里最脏最累但最关键的环节。我处理电子病历数据时有几条铁律:

  • 明确暴露定义和暴露时间,剔除“暴露状态不明确”的病例。比如首诊后30天内才开新药的患者,到底算不算暴露组?需要敏感性分析来处理。
  • 结局事件的定义要统一。心梗是只看主要诊断,还是也看急诊诊断、死亡证明?不同定义对结论影响很大。
  • 缺失数据的处理要提前规划。协变量缺失率超过20%的变量要谨慎;重要混杂缺失时,考虑多重插补,但一定要在PS模型层面就纳入插补后的数据。

PS模型我一般用logistic回归,暴露作因变量,协变量是DAG的最小调整集。变量个数不宜太多,一般不超过事件数的十分之一,否则就容易过拟合。跑出来的PS会输出每个个体的倾向得分,在R里也就两三行代码:

# 构建PS模型 ps_model <- glm(treat ~ age + sex + bmi + hba1c + hypertension + dyslipidemia + egfr, data = cohort, family = binomial) # 计算倾向得分 cohort$ps <- predict(ps_model, type = "response") # 检查两个组PS分布重叠情况 summary(cohort$ps[cohort$treat == 1]) summary(cohort$ps[cohort$treat == 0])

匹配环节我推荐用最近邻匹配加卡钳值。卡钳值的经验值是0.2倍PS标准差,太小会丢失大量样本,太大会降低平衡质量。匹配比例上,1:1匹配简单直观,但样本利用效率低;1:4匹配可以保留更多信息,但需要检查配对质量。实操中我会同时做1:1和1:4,看结论是否一致。

匹配完成以后,标准动作是检查SMD和PS重叠图。SMD的计算并不复杂,在R里可以用tableone包一键输出。我习惯把所有协变量做成一张表格,匹配前SMD高的一组和匹配后SMD全部小于0.1的一组并排看,审稿人最喜欢看到这种结果呈现。

3.3 效应估计与敏感性分析矩阵

PS匹配后,可以用匹配样本直接建Cox或logistic回归估计HR或OR,也可以在未匹配的完整样本上做IPTW加权后进行加权回归。还有两种更稳健的做法:一种是“双重稳健估计”,即同时把PS和协变量放进结局模型,只要PS模型和结局模型有一个正确,估计就是一致的;另一种是“G计算”,用参数模型模拟每个人的潜在结局,再取平均。

我个人推荐在主要分析中采用“IPTW加权+协变量调整”的双重稳健策略,并在附录里补充PS匹配的结果,作为稳健性检验。处理效应一般用风险差和风险比同时汇报,公卫领域只给HR不给绝对风险是常常被审稿人质疑的,绝对风险才能真正说明公共卫生负担。

所有因果分析做完了,还必须做敏感性分析。我的标配矩阵是三件事:

  • E值(E-value):算一下,如果存在未测混杂,要把效应估计解释为因果所需的混杂强度需要多大。比如HR=1.5,E值=2.3,那么未测混杂与暴露和结局的关联至少要达到2.3倍才能把效应完全解释掉。如果这个值很小,说明结论经不起未测混杂的冲击。
  • 阴性对照:选一个理论上与暴露无关、但与结局有已知关联的变量,验证你的分析流程不会产生虚假关联。比如研究降压药与心梗的关系,可以用“意外伤害死亡”做阴性对照结局,如果分析后降压药与意外伤害显著相关,说明有残余混杂。
  • 假暴露对照:把暴露定义整体向后平移一段时间,重新算一遍效应。如果只平移30天效应就消失,说明可能存在反向因果或者适应症混杂。

4. 常见问题与排查技巧实录

4.1 选择偏倚和适应症混杂是公卫老熟人

做药物流行病学的人最怕一个词——适应症混杂(confounding by indication)。通俗讲,不是因为药导致了好/坏结局,而是“医生为什么给病人开这个药”本身就与预后相关。病情重的可能用更强效的新药,病情轻的留在老药,两组结局差异直接反映的是病情差异。

针对适应症混杂,一个有用的排查技巧是观察“处方时的临床指标”。比如比较新药和老药,就要认真对比两组在处方时的血压、血糖、肾功能、心功能分级。如果差异很大,即使PS匹配后SMD达标了,也要警惕是否存在某些“驱动处方的未测因素”。这类因素通常包括医生偏好、患者依从性、医疗资源可及性,很难在病历数据里看到。

还有一种特殊的选择偏倚叫不朽时间偏倚。在药物流行病学里,你定义一个“使用者”必须活过某个时间窗,这段生存时间片段被错误地归入“暴露组”,就会虚增保护效应。处理方案是采用时间依存暴露模型或新用户设计。新用户设计就是在cohort里只纳入刚开始用药的患者,排除“老用户”,能消除很多幸存者偏倚。这个设计在我看来是公卫因果分析里最高性价比的招数,新手一定要用。

4.2 时变混杂和中介效应纠缠不清

很多公卫研究暴露和结局之间隔了很长的随访期,中间变量本身会被暴露影响,又会反过来影响后续暴露。比如研究降压药对心衰的影响,随访中血压控制情况既是药物作用的结果,又是后续治疗调整的依据。这就是时变混杂,普通回归会严重偏倚。

处理时变混杂的武器是G方法家族,包括G公式、逆概率加权边际结构模型(MSM)、G-estimation。其中MSM的思路是给每个时间点的暴露加权,权重用该时间点的PS计算,以此切断时变混杂的反向路径。这个方法在纵向数据里非常实用,但写代码时要注意权重的截断问题,权重太大时结果会被极少数个体主导,我一般会截断在1%和99%分位数。

中介分析也是公卫因果里绕不开的话题。如果DAG显示某个变量是暴露到结局的中间路径(比如血糖控制是降糖药到微血管结局的中介),就不能把它放进调整集,而是要单独做中介分解。传统Baron-Kenny方法问题很多,现在更推荐用反事实中介分析,把总效应分解为自然直接效应和自然间接效应,并给出相应的置信区间。R里有mediation包可以跑,但要注意它要求“无未测混杂”适用于暴露-中介、中介-结局、暴露-结局多条路径,这是个很强的假设。

4.3 多重比较与p值依赖:如何让结论站得住

观察性因果研究特别容易犯“反复试模型、选最小p值”的错误。你今天试了五种调整方案,选了最好看的那组汇报,这个p值已经不诚实了。公卫研究的产出要支撑公共决策,比p值更重要的是效应方向的一致性和敏感性分析的稳定性。

我自己的做法是:分析方案在跑数据前就在预注册平台(比如Open Science Framework)上写好,包括DAG、主要分析方法、敏感性分析矩阵。数据跑完以后,所有分析都按照计划执行,额外的探索性发现单独标注“探索性分析”。这个习惯帮助我规避了大量“事后合理化”问题。

另一个很常见的实战问题是:大型电子病历数据几乎任何关联做出来都是显著的,但效应量可能小到没有公共卫生意义。所以我在汇报结果时,会同时给效应量置信区间、绝对风险差、NNT(需要治疗的人数),让读者直观判断“这个效果值不值得推广”。一个HR=1.05的结果,哪怕p<0.001,可能也只是统计学显著,实际意义非常有限。

5. 写在最后的一点个人体会

坦白讲,方法论工具再丰富,也补不上“研究设计没想清楚”的洞。这些年我做公卫因果项目,最大的进步不是学会了多少新模型,而是养成了先画DAG、先问假设、先做新用户设计、再碰统计模型的习惯。因果推断不是一种“更高级的回归”,而是一套关于“你怎么获得可比较的组”的思维框架,想通这个,很多方法自然就知道什么时候该用、什么时候不该用。

最后分享一个实际操作中的小技巧:把主要分析和敏感性分析的代码写进同一个R Markdown文件,每次改一个参数就重新渲染一次,保证分析链路可复现。审稿人索要代码和结果时,直接给渲染后的HTML,信任度会高很多。公共卫生研究是给人命做决策用的,每一步都值得较真。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询