
说起来有点意思我最早接触“因果推断”并不是因为追什么方法学热点而是被一个临床问题逼的。那时候手里握着一批电子病历数据老板想知道某个新型降糖药是不是比老药更能降低心梗风险。逻辑很简单两组病人一组吃新药一组吃老药比一比心梗发生率不就行了结果一做生存分析新药组的心梗率反而更高。后来才反应过来开新药的那帮人往往病情更重、合并症更多基线就不齐。那一刻我就明白公共卫生里真正难的不是“算出个结果”而是搞清楚“这个结果能不能当因果用”。这篇文章我想认真聊聊公共卫生领域的因果实践。不扯太多数学证明就从实际做项目的角度讲讲在观察性数据里怎么逼近因果效应、有哪些趁手的工具、核心步骤怎么落地、以及我踩过哪些坑。适合刚接触因果推断的临床研究者、流行病学研究生还有那些手里有回顾性数据但不知道该怎么“挖”出一篇高质量文章的同行。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 ScorePS是 Rosenbaum 和 Rubin 在1983年提出的概念定义为“给定一组协变量X的条件下个体接受暴露E的概率”即P(E1|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统计量检验F10说明工具变量与暴露的关联太弱结果不可靠二是水平多效性也就是基因位点可能通过其他通路影响结局这个需要做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算一下如果存在未测混杂要把效应估计解释为因果所需的混杂强度需要多大。比如HR1.5E值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需要治疗的人数让读者直观判断“这个效果值不值得推广”。一个HR1.05的结果哪怕p0.001可能也只是统计学显著实际意义非常有限。5. 写在最后的一点个人体会坦白讲方法论工具再丰富也补不上“研究设计没想清楚”的洞。这些年我做公卫因果项目最大的进步不是学会了多少新模型而是养成了先画DAG、先问假设、先做新用户设计、再碰统计模型的习惯。因果推断不是一种“更高级的回归”而是一套关于“你怎么获得可比较的组”的思维框架想通这个很多方法自然就知道什么时候该用、什么时候不该用。最后分享一个实际操作中的小技巧把主要分析和敏感性分析的代码写进同一个R Markdown文件每次改一个参数就重新渲染一次保证分析链路可复现。审稿人索要代码和结果时直接给渲染后的HTML信任度会高很多。公共卫生研究是给人命做决策用的每一步都值得较真。