04 因果推断的稳健性基石:平行趋势与安慰剂检验
1. 为什么需要稳健性检验?
当你用双重差分法(DID)得出一个漂亮的政策效应估计时,审稿人总会抛出那个灵魂拷问:"这结果真的由政策导致吗?"我刚开始做政策评估时就吃过这个亏——花了三个月做的农民工培训政策分析,被评委一句"内生性问题没解决"直接打回。后来才明白,因果推断就像破案,不能只看表面证据,得排除所有其他可能性。
内生性威胁就像躲在阴影里的"真凶"。比如企业出口增长可能源于行业景气周期,而非你研究的自贸区政策;教育投入效果可能反映地区财政实力,而非政策本身。这时候就需要两类"侦探工具":平行趋势检验验证案件前提,安慰剂检验模拟无政策场景。我在帮某省政府做评估时,就曾用安慰剂检验发现原本显著的环保政策效应,其实是同期降雨量增加导致的。
2. 平行趋势检验:政策前的双重验证
2.1 时间趋势图的实战技巧
绘制处理组和控制组的均值走势图是最直观的方法,但魔鬼在细节里。我常用这个Stata代码模板:
// 计算政策前后各3年的窗口期 gen period = year - policy_year forvalues i = 3(-1)1 { gen pre_`i' = (period == -`i' & treated == 1) } gen current = (period == 0 & treated == 1) forvalues j = 1(1)3 { gen post_`j' = (period == `j' & treated == 1) } // 回归时加入年份固定效应 reghdfe y pre_* current post_* i.year, absorb(city) vce(cluster city)关键要看三点:
- 政策前各期系数是否在0附近波动(置信区间包含0)
- 政策后效应是否显著分离(置信区间排除0)
- 转折点是否出现在政策时点。有次我发现效应提前一年出现,原来是被评估地区提前获知了政策消息。
2.2 事件研究法的进阶应用
当政策实施时间不统一时(比如各城市不同年份推行垃圾分类),传统DID会失效。这时可以用动态效应模型:
// 生成相对时间虚拟变量 gen rel_year = year - policy_year tab rel_year, gen(rydum) forval i = 1/7 { gen treat_ry`i' = treated * rydum`i' } // 剔除-1期作为参照 xtreg y treat_ry* i.year, fe注意要处理"堆叠DID"的潜在问题。有篇研究高铁经济的论文,就因忽略城市在不同年份开通高铁的异质性,导致平行趋势检验失效。我的经验是:对连续处理变量,改用渐进DID(Continuous DID)框架更稳妥。
3. 安慰剂检验的六种武器
3.1 虚构政策时间:顶级期刊的标配
《经济研究》上80%的DID论文都会做这个检验。具体操作:
- 将真实政策时间提前1-3年
- 仅使用政策前样本
- 重复估计过程
// 假设真实政策在2015年,虚构为2013年 gen fake_policy = (year >= 2013) & treated xtreg y fake_policy i.year, fe如果虚构的政策变量依然显著,说明原结果可能捕捉到了预存趋势。我曾见过某研究产业政策的论文,虚构时间检验全部不显著,审稿人立刻给过。
3.2 随机分配处理组:蒙特卡洛模拟
这是最严苛的检验之一,需要编写循环程序:
// 保存真实估计值 xtreg y treated_post i.year, fe scalar true_coef = _b[treated_post] // 随机分配处理组500次 matrix results = J(500,1,.) forvalues i = 1/500 { gen random_treat = runiform() > 0.5 gen random_post = (year >= policy_year) gen random_effect = random_treat * random_post qui xtreg y random_effect i.year, fe matrix results[`i',1] = _b[random_effect] } // 绘制系数分布图 mata: st_matrix("results", results) kdensity results[,1], xline(`=true_coef') title("安慰剂检验")某次我用这个方法发现,真实系数落在随机系数分布的右尾1%位置,极大增强了结论可信度。
3.3 替换变量:巧妙的证伪测试
选理论上不受政策影响的变量:
- 研究环保政策时,用员工工资增长率作为替代被解释变量
- 分析创新补贴时,用企业广告支出作为对照
// 用非目标变量检验 xtreg advertising treated_post i.year, fe这个方法的妙处在于双向验证:既要用目标变量得出显著结果,又要用非目标变量得到不显著结果。有篇研究最低工资的论文,发现政策既提高了工资,又"意外"降低了员工离职率——后者显然不符合理论预期,作者最终承认存在遗漏变量问题。
4. 综合应用案例解析
去年参与某自贸区评估项目时,我们完整实施了这套检验方案:
平行趋势检验:发现进出口额在政策前5年满足平行趋势,但GDP增长率处理组原本就更高,于是改用"GDP增速差值"作为被解释变量。
安慰剂检验:
- 虚构政策时间:2013-2014年系数均不显著
- 随机分配:500次模拟中仅2.4%的系数大于实际估计值
- 替换变量:对"电影院银幕数量"无显著影响
附加检验:
// 分样本回归 bysort industry: xtreg y treated_post i.year, fe // 动态效应 gen year_since = year - policy_year tab year_since, gen(ysdum) forval i = 1/5 { gen treat_ys`i' = treated * ysdum`i' } xtreg y treat_ys* i.year, fe
最终报告用16种不同检验方法排除了内生性质疑,获得国务院发展研究中心的高度认可。这让我深刻体会到:因果推断不是追求漂亮系数,而是构建无懈可击的证据链。