合成控制法(SCM)是我工具箱里的“王牌工具”——它完美解决了“处理组只有一个个体,找不到合适对照组”的痛点,比如“评估上海房产税政策的效果”“估计新冠疫情对某国经济的影响”。今天就结合我自己的实操经验,把合成控制法的原理、代码和避坑指南整理出来,新手也能直接上手。
先搞懂合成控制法的核心逻辑:为什么它能解决“独苗”处理组的问题?
很多人刚接触SCM时会问:“处理组只有一个,怎么估计因果效应?”其实SCM的核心逻辑特别接地气:
- 当处理组只有一个个体(比如一个国家、一个省份、一个企业),找不到合适的对照组时,我们可以通过加权组合多个控制单元,构建一个“合成控制组”——这个合成组在处理前的特征和趋势上与处理单元尽可能相似
- 比如我们要评估上海房产税政策的效果,找不到一个和上海完全一样的城市,但我们可以找北京、广州、深圳等城市,给它们赋予不同的权重,构建一个“合成上海”
- 政策实施后,真实上海和合成上海在结果变量上的差异,就是政策的处理效应
简单来说,合成控制法就是利用“加权组合多个控制单元”的特性,为处理组量身打造一个“最佳替身”。比如我们可以用它来分析“政策冲击对单个个体的影响”“突发事件对某地区经济的影响”。
哪些场景适合用合成控制法?别瞎用!
不是所有问题都能套合成控制法,我一般在这几种场景下会用它:
- 单个处理个体的政策评估:比如“上海房产税政策对房价的影响”“某企业并购对其绩效的影响”
- 突发事件的影响评估:比如“新冠疫情对某国GDP的影响”“自然灾害对某地区农业产量的影响”
- 稀有事件的研究:比如“某行业技术突破对该行业发展的影响”“某地区重大改革对其经济的影响”
- 无法找到合适对照组的研究:比如“某独特政策对某地区的影响”“某创新产品对市场的影响”
一句话总结:当处理组只有一个个体,且无法找到合适的对照组时,合成控制法就是你的最佳选择。
Stata实操:手把手教你用合成控制法
我用Stata自带的美国各州香烟销售数据(smoking.dta)来演示,你可以换成自己的数据。
1. 数据准备:先把数据设置为面板数据
首先,我们需要导入数据,并将其设置为面板数据。 Stata代码:
sysuse smoking, clear // 导入数据
tsset state year // 将数据设置为面板数据
这个数据里,state是州代码,year是年份,cigsale是人均香烟销售量(结果变量),lnincome是人均收入对数,age15to24是15-24岁人口比例,retprice是香烟零售价格,beer是人均啤酒消费量。
2. 基本合成控制法估计:构建“合成加州”
接下来,我们用synth命令估计合成控制法,评估加州1989年实施的控烟政策对香烟销售量的影响。 Stata代码:
synth cigsale lnincome age15to24 retprice beer cigsale(1988) cigsale(1980) cigsale(1975), trunit(3) trperiod(1989) fig nested keep(synth_results_data.dta) replace
- 参数说明:
cigsale:结果变量(人均香烟销售量)lnincome age15to24 retprice beer:预测变量(用于构建合成控制组的特征变量)cigsale(1988) cigsale(1980) cigsale(1975):结果变量的滞后值(用于匹配处理前的趋势)trunit(3):处理组单元(加州的州代码是3)trperiod(1989):处理开始的年份(1989年开始实施控烟政策)fig:绘制处理组和合成控制组的结果变量趋势图nested:使用嵌套优化算法寻找最优权重keep(synth_results_data.dta):保存合成控制组的结果到指定文件
执行完这个命令后,Stata会输出合成控制组的权重,以及处理组和合成控制组的结果变量趋势图。

3. 加载并分析合成控制组的结果
我们可以加载刚才保存的结果文件,进一步分析合成控制组的结果。 Stata代码:
use synth_results_data.dta, clear // 加载合成控制组的结果
drop _Co_Number _W_Weight // 删除不必要的变量
twoway line (_Y_treated _Y_synthetic _time), scheme(plottig) xline(1989) xtitle(Year) ytitle(Cigarette Sales) legend(pos(6) rows(1))
这个命令会绘制处理组(真实加州)和合成控制组(合成加州)的人均香烟销售量趋势图,其中xline(1989)会在1989年(政策实施年份)画一条垂直参考线。
4. 稳健性检验:安慰剂检验
为了验证合成控制法的结果是否稳健,我们可以做安慰剂检验——把其他州当作处理组,重复合成控制法估计,看看处理效应是否显著。 Stata代码:
ssc install synth_runner // 安装synth_runner命令
sysuse smoking, clear // 重新导入数据
tsset state year // 将数据设置为面板数据
synth_runner cigsale lnincome age15to24 retprice beer cigsale(1988) cigsale(1980) cigsale(1975), trunit(3) trperiod(1989) gen_vars
- 参数说明:
synth_runner:运行合成控制法的安慰剂检验gen_vars:生成用于分析的变量
执行完这个命令后,Stata会生成一个包含所有安慰剂检验结果的数据集,我们可以绘制处理效应的分布直方图,看看真实处理效应是否显著大于安慰剂效应。
5. 绘制安慰剂检验结果
最后,我们可以绘制安慰剂检验的结果,直观展示处理效应的显著性。 Stata代码:
synth_runner_graph, all // 绘制所有安慰剂检验的结果
这个命令会绘制所有安慰剂检验的处理组和合成控制组的结果变量趋势图,以及处理效应的分布直方图。
结果解读:重点看这几个指标
每次跑出来合成控制法的结果,我都会先看这几个关键指标:
- 合成控制组的权重:看看哪些控制单元被赋予了较高的权重,比如加州的合成控制组可能主要由纽约、得克萨斯等州组成
- 处理前的拟合程度:看看合成控制组在处理前的结果变量趋势是否与处理组高度相似——拟合程度越高,结果越可靠
- 处理后的差异:看看处理组和合成控制组在处理后的结果变量差异——差异越大,政策效果越显著
- 安慰剂检验结果:看看真实处理效应是否显著大于安慰剂效应——如果真实处理效应在所有安慰剂效应的分布中处于极端位置,说明政策效果显著
论文应用技巧:让审稿人眼前一亮
- 图比表重要:论文里一定要放处理组和合成控制组的结果变量趋势图,直观展示处理前后的差异,比一堆数字有说服力
- 多做稳健性检验:除了安慰剂检验,还可以换预测变量、换处理组单元、换处理开始年份,验证结果的稳健性
- 解释要接地气:别光说“处理效应显著”,要解释成“加州实施控烟政策后,人均香烟销售量比合成加州低20%,这说明控烟政策确实有效”
- 和其他方法对比:可以和双重差分法(DID)的结果对比,突出合成控制法的优势——比如“DID估计的政策效果是15%,但合成控制法估计的是20%,说明DID可能存在对照组选择偏差”
避坑指南:这些坑我都踩过,你别再踩了
- 处理前时期要足够长:处理前时期越长,合成控制组的拟合程度越高,结果越可靠——一般来说,处理前时期至少要有5年
- 控制单元要合适:控制单元应该与处理单元具有相似的特征,比如评估上海的政策效果,控制单元应该选择其他一线城市
- 预测变量要选择合理:预测变量应该是影响结果变量的重要因素,且在处理前的趋势与处理单元相似
- 不要过度解读结果:合成控制法只能估计处理组和合成控制组之间的差异,不能推广到其他个体——比如你不能用上海的政策效果去推断其他城市的政策效果

4597

被折叠的 条评论
为什么被折叠?



