2023年,我为一个连锁零售品牌做新店补贴政策效评估。市场部总监指着屏幕上一条漂亮的趋势线说:“你看,补贴政策一上线,新店销售额就涨了30%,这政策效果立竿见影。”我问他:“那如果没有补贴,这30%的增量本来应该有多少?”他愣住了。这个问题,就是合成控制法要回答的核心问题。在真实商业分析和政策评估中,我们需要的不是“政策后A比B好多少”,而是“如果政策没发生,A会变成什么样”。合成控制法,是目前业界公认回答后一个问题的黄金标准。

在做政策评估时,几乎所有人都会想到双重差分法(DID)。DID的逻辑很直观:找一个对照组,看政策前后两组的变化差。但DID有一个前提假设,平行趋势(Parallel Trend):如果没有政策干预,处理组和对照组的结果变量会沿着相同的路径变化。
问题在于,在真实的商业环境和政策场景中,平行趋势假设几乎从不成立。一个城市、一个门店、一个区域之所以被选为“试点”,往往是因为它本身就有某种特殊性。这种特殊性,恰恰导致它和任何单一对照组都不会有相同的“未来轨迹”。
合成控制法的核心价值在于:它放弃了一个“完美”的对照组,转而“构造”一个。它从一组潜在的控制单元(称为“供体池”)中,按相似性赋予权重,拼出一个和“处理组”在政策实施前几乎一模一样的“合成对象”。这个合成对象,就是政策干预发生在处理组身上的“反事实”版本。
很多人看到“合成控制”四个字,就认为是少数统计学家的工具。实际上,它的核心逻辑非常直观:
这就是合成控制法的独特视角:它不追求“找到一个完美的对照组”,而是接受“没有完美对照组”的现实,然后用数据构造一个。
回到开头那个案例。我们评估的是某个连锁零售品牌在2022年Q2对12家新开门店实施的“首月补贴”政策。处理组是这12家试点门店,供体池是同期开业的、未享受补贴的另外60家门店。
我们用合成控制法为每家试点门店构造了一个“合成门店”。结果发现:
这11%的自然差异,就是DID无法捕捉的“选择偏差”。处理组门店之所以被选为试点,很可能是因为它们本身就处于潜力更优的商圈。合成控制法把它剥离了出来。
数据来源: 某连锁零售品牌2022年Q2新店补贴效果评估项目
合成控制法的第一步,也是最重要的一步,是定义“供体池”,也就是可以用来合成处理组的那些单元。供体池的选择直接影响最终结果的质量。
供体池选择规则:
预测变量的选择:
预测变量是那些影响结果变量(比如销售额)的协变量。合成控制法会通过最小化这些变量在处理组和合成对象之间的“均方预测误差(MSPE)”,来找到最优的权重。
常见的预测变量包括:
一个重要的经验判断: 不要贪多。预测变量太多会导致“过拟合”,合成的对象在政策前拟合得很好,但政策后的预测会变得不稳定。通常,5-10个高相关性的预测变量,再加政策前10-20个时间点的结果变量数据,就足够了。
合成控制法的数学核心是一个优化问题:找到一组权重(每个供体池单元一个权重,所有权重之和为1),使得处理组和合成对象的预测变量之差最小化。
具体操作:
假设处理组有预测变量向量X1,供体池有预测变量矩阵X0。我们需要找到权重向量W,使得 ||X1 – X0*W|| 最小。这个“距离”通常用均方误差表示。
在R语言中,实现这一过程非常简洁:
# 安装并加载Synth包
install.packages("Synth")
library(Synth)
假设数据框为df,包含id、time、outcome(结果变量)、predictors(预测变量)
准备数据
dataprep.out <-
dataprep(
foo = df,
predictors = c("area", "population", "gdp"),
predictors.op = "mean",
dependent = "sales",
unit.variable = "store_id",
time.variable = "month",
treatment.identifier = 1, # 处理组的ID
controls.identifier = c(2:50), # 供体池的ID
time.predictors.prior = c(1:12), # 政策前的时间点
time.optimize.ssr = c(1:12), # 用于优化权重的时期
unit.names.variable = "store_name",
time.plot = 1:24 # 完整时间序列
)
运行合成控制
synth.out <- synth(data.prep.obj = dataprep.out)
生成结果
path.plot(synth.out, dataprep.out)
输出解读:
有了合成控制的结果,我们得到了两条曲线:处理组的真实路径,和合成对象的“反事实”路径。政策效果就是两条曲线在政策实施后的差距。
但问题来了: 这个差距,是“真的”还是“碰巧”的?
合成控制法不使用传统的P值来做统计推断,因为它本质上是一个小样本方法。相反,它使用一种叫做“安慰剂检验(Placebo Test)”的推断方法。
安慰剂检验的操作步骤:
一个经验判断: 如果真实处理组的效果曲线,在安慰剂检验图中,明显“跑出”了所有假处理组的曲线带,那这个结果就是“肉眼可见”的显著。如果它淹没在假效果曲线中,那无论统计P值多小,都说明结果不可靠。
数据来源: 某连锁零售品牌新店补贴效果评估项目,数据经过脱敏处理
合成控制法最经典的应用,就是评估一个“只在一个地方、一次全面实施”的政策。比如:
这类场景的共性: 只有一个处理单元,且政策是“一次性”的。DID需要多个处理单元,RDD需要断点,匹配法需要大样本。只有合成控制法,能处理这种“独苗”场景。
行动建议: 如果企业只有某个试点城市、试点门店或试点区域实施了新政策,且其他区域没有实施,那么合成控制法就是唯一可用的因果推断方法。
大多数政策评估都是“事后”的,政策实施后,我们来评估效果。但合成控制法打开了另一个可能性:“如果我们在某个地方实施了政策,结果会怎样?”
具体做法:
假设你要在某个城市A实施新政策,但城市A还没有实施。你可以用城市A在政策前的数据,和供体池(其他类似城市),合成一个“城市A”,然后看这个合成对象在未来会如何发展。这个“合成对象”的预测,就是政策不实施时的基准线。
一个真实案例:
2021年,我为一个零售品牌评估“是否应该在某省会城市开设第一家旗舰店”。我们用了该城市周边5个类似城市的门店数据,用合成控制法构造了“该城市如果不开旗舰店”的销售预测。然后,我们对比了“开旗舰店”的预期收益和“不开旗舰店”的合成预测,发现旗舰店带来的增量远远低于预期,建议暂缓。结果,该品牌采纳了建议,后来市场环境恶化,证明了当时的判断。
关键判断: 合成控制法不仅是一个“事后归因”工具,更是一个强有力的“事前推演”工具。它让决策者能够“预演”政策的效果,而不是事后才后悔。
在商业分析中,最常遇到的困境是:“我们做了很多事,但不知道哪件事起了作用。”
合成控制法可以帮助剥离“政策效应”和“自然趋势”。
一个典型场景:
某电商平台在618大促期间,同时对“新用户”推出了“首单补贴”政策。结果,新用户的转化率确实提升了。但问题是,618大促本身就会带来整体转化率的提升。如何区分“补贴”的效果和“大促”的效果?
解决方案:
通过合成控制法,我们可以构造出“新用户如果没有补贴,但受大促影响”的合成对象,从而剥离出补贴的净效果。
数据来源: 某电商平台2022年618大促用户补贴效果评估,合成控制法应用推演
问题: 如果供体池中的某个单元,也受到了“类似政策”的影响,那它就不能用来“合成”未受政策影响的状态。
案例: 评估“A城市环保政策对空气质量的影响”,供体池中包含了B城市。但B城市在同一时期也实施了类似环保政策。那么,用B城市的数据去合成“未受政策影响的A城市”,结果就会偏大。
解决方案: 仔细检查供体池中每个单元的政策背景,排除任何受到“同类政策”影响的单元。
问题: 合成对象在处理组政策前的MSPE很大,说明合成质量很差。但分析者仍然强行解释政策后的效果。
经验判断: 政策前的MSPE如果超过10%,那合成对象就不是一个“好的反事实”。政策后的任何效果,都可能是“合成失败”带来的噪声,而不是政策导致的。
行动建议: 如果MSPE超过10%,尝试以下方法:
问题: 政策对处理组的效果,可能“溢出”到供体池中的单元,从而污染供体池。
案例: 评估“A城市发放消费券”对线下消费的影响。消费券可能吸引B城市、C城市的居民到A城市消费,导致B、C城市的消费数据被“污染”。如果用B、C城市的数据去合成A城市的反事实,结果就会偏小。
解决方案: 在政策实施后,检查供体池单元的表现是否“异常”。如果发现供体池单元的政策后趋势发生了明显变化,就应该排除它们。
问题: 合成控制法的结果图非常直观、漂亮,容易让人产生“结果显著”的错觉。但图形上的“分离”并不等于统计意义上的“显著”。
经验判断: 一定要做安慰剂检验。如果安慰剂检验的结果显示,真实处理组的效果不是特别突出,那就要谨慎对待。
一个辅助判断: 计算“效果-安慰剂比率”:真实处理组的效果 / 所有安慰剂效果的90%分位数。如果这个比率大于3,说明效果很强;在1.5-3之间,说明效果中等;小于1.5,说明效果不明显。
问题: 合成控制法是一个强大的工具,但不是一个“万能钥匙”。它在某些场景下非常有效,但在某些场景下可能不如DID或RDD。
适用场景总结:
| 评估场景 | 推荐方法 | 原因 |
|---|---|---|
| 单个处理单元,政策一次性实施 | 合成控制法 | 其他方法无法处理单个处理单元 |
| 多个处理单元,随机分配 | DID / RCT | 随机性保证了平行趋势 |
| 多个处理单元,非随机分配 | DID + 匹配 / 合成控制法 | 用匹配或合成控制法处理选择偏差 |
| 处理单元在断点附近 | RDD | 断点附近近似随机 |
| 处理单元数量小,但时间序列长 | 合成控制法 | 利用时间序列信息构造反事实 |
合成控制法在优化权重时,会用到“政策前的时间窗口”。这个窗口的选择,会影响最终权重。一个稳健的结果,应该在不同窗口下都成立。
操作建议:
如果三种窗口下的结果方向一致,那结果就比较稳健。如果方向发生变化,那就要非常谨慎。
供体池的选择也会影响结果。一个稳健的结果,应该在不同供体池下都成立。
操作建议:
一个经验判断: 如果剔除权重最高的单元后,结果消失或反转,说明合成的结果高度依赖这几个单元,结果不可靠。
除了空间上的安慰剂检验(把政策分配给其他单元),还可以做时间上的安慰剂检验。
操作: 把“政策实施时间”提前1年、2年,看是否会出现“假效果”。
判断标准: 如果提前政策时间后,也出现了“效果”,那说明这个“效果”不是由真实政策导致的,而是由某种时间趋势导致的。
数据来源: 基于某零售品牌数据的时间安慰剂检验模拟
当你面对一个需要评估政策效果的问题时,可以按照以下步骤来决策:
一个重要的“取舍”原则: 合成控制法追求的是“因果推断的准确性”,而不是“统计上的显著性”。在样本量小的情况下,一个“不显著”但“方向稳定”的结果,比一个“显著”但“方向不稳定”的结果,更有决策价值。
回到开头那个问题:“如果没有补贴,这30%的增量本来应该有多少?”
合成控制法给了我们一个答案。它不是一个“完美”的答案,但它是“可计算”的答案。它让我们从“看政策后的结果”转向“看政策带来的净效果”。它让我们能在“不确定”的世界里,做出更“确定”的决策。
下一步做什么?
如果你是一个数据分析师,开始尝试用合成控制法评估你身边的政策或商业决策。找一个你熟悉的案例,收集数据,用R或Python实现一次。不要追求“完美”的结果,而是理解“过程”。
如果你是一个决策者,下次听到“政策效果显著”时,问问对方:“请问,这个‘显著’是‘和什么比’的显著?有没有用合成控制法做过‘反事实’分析?”
合成控制法不是万能的,但它让“如果”变得可计算。而“可计算”,是理性决策的起点。
我刚开始用合成控制法,看到结果中权重分配很不均匀,有些州权重接近0,有些州权重很高。我不确定这是否正常,是否意味着合成效果不好?权重到底是怎么算出来的?
权重的确定是通过最小化干预前时期真实干预单元与合成控制单元之间的均方预测误差(MSPE)来实现的。算法会寻找一组非负权重(和为1),使得在干预前的时间段内,合成控制单元的预测变量(如GDP、人口、产业结构等)尽可能接近真实干预单元。
权重集中在少数几个州通常意味着这些州在预测变量上与干预单元非常相似,而其他州差异较大。这本身不一定有问题,但如果权重过度集中(比如只有一个州权重接近1),则合成控制可能只是简单复制了该州,失去了“合成”的意义,此时结果可能不可靠。
我的经验是,当权重分布比较均匀时,合成效果通常更好,因为综合了多个单元的信息。如果权重集中,建议检查预测变量的选择是否合理,或者考虑是否干预单元本身与其他单元差异过大,导致无法有效合成。
我曾经评估一个地方性环保政策时,发现权重几乎全落在邻省,后来发现是因为我只用了地理距离作为预测变量,加入经济结构变量后权重才分散开。
我看了很多教程,都说要用安慰剂检验,但具体怎么计算P值?是不是像传统统计那样有个公式?我画出了安慰剂检验的图,但不知道如何判断是否显著。
合成控制法的统计推断不依赖于传统的标准误,而是通过安慰剂检验来评估效果的“罕见程度”。基本思路是:假设政策干预发生在其他未受干预的单元(即控制组中的每个单元),对每个单元都进行一次合成控制分析,得到一系列“安慰剂效果”。然后,比较真实干预单元的效果与这些安慰剂效果。
如果真实效果在所有安慰剂效果中处于极端位置(例如,比95%的安慰剂效果都大),则认为结果在统计上显著。计算P值的常用方法是:将真实干预后MSPE与安慰剂干预后MSPE的比值排序,计算真实比值大于多少比例的安慰剂比值。例如,如果真实比值大于95%的安慰剂比值,则P值约为0.05。
注意,这里P值不是精确的,而是基于排序的。在实际操作中,我会同时报告“真实效果是否在安慰剂分布的最外侧”以及“干预后MSPE比值”作为证据。另外,要小心如果干预前合成效果很差(MSPE很大),那么安慰剂检验可能不可靠,因为合成效果差意味着模型本身拟合不好。
我遇到过一种情况:干预前MSPE已经很大,安慰剂检验显示效果显著,但更换预测变量后结果不显著,这说明初始的合成质量有问题,需要先优化合成阶段。
我想评估一个全国性的政策,所有省份都实施了,没有明显的控制组。我看到合成控制法需要一个未受干预的对照组,但我的情况是所有人都受到了干预,那还能用吗?
合成控制法最初设计用于评估单个单元(如一个州、一个城市)的政策效果,要求有多个未受干预的单元作为“供体池”。如果所有单元都同时受到干预,则无法构造反事实。但有两种变通方法:第一,如果政策实施时间在不同地区有先后,可以将较早实施政策的地区作为干预组,较晚实施的作为控制组(但要注意预期效应);
第二,可以使用“时间合成控制”或“面板数据方法”,但严格来说,合成控制法不适用于全样本干预。我的建议是,如果所有单元都同时受干预,可以考虑其他方法如中断时间序列或双重差分,但双重差分需要平行趋势假设。如果你仍然想用合成控制,可以尝试将干预单元与其他国家的类似地区作为供体池,但要注意数据可比性。
我曾在评估一个行业政策时,由于所有同行都受影响,我选择了不同行业的类似公司作为供体,但需要论证这些公司在关键特征上可比。最终我通过匹配行业特征(如资产规模、营收结构)构造了供体池,并进行了稳健性检验,结果才被认可。
我一直在用双重差分做政策评估,但最近听说合成控制法更好,不需要平行趋势假设。是不是以后都应该用合成控制?它有什么缺点吗?
合成控制法的主要优势在于它不要求平行趋势假设,而是通过数据驱动的方式构造一个更相似的控制组,从而减少了主观选择偏差。此外,它明确展示了每个控制单元的权重,增加了透明度。但是,合成控制法也有局限性:第一,它要求有足够长的干预前数据(通常建议至少10期以上)来拟合合成控制;
第二,它只能评估单个干预单元(或少数几个)的效果,对于多个干预单元需要分别处理;第三,它不能处理溢出效应(即政策对控制组产生影响);第四,统计推断依赖安慰剂检验,在小样本下可能不够稳健。
我的判断是:当你有一个明确的干预单元(如一个州、一个公司)和多个潜在控制单元,且干预前数据充分时,合成控制法是首选。但如果你有多个干预组和控制组,且平行趋势假设可能成立,双重差分仍然有效且更简单。在实际工作中,我经常同时使用两种方法进行稳健性检验。
例如,在评估某电商平台的促销活动时,我用合成控制法构造了未促销地区的反事实,同时用双重差分比较促销与非促销地区,结果一致则增强信心。如果两者冲突,我会深挖数据质量或模型设定问题,而不是盲目相信某一种方法。


上一篇:数据分析之公平约束 – 后处理
读者评论
作为数据分析师,最打动我的是那个11%的自然差异,之前用DID总被质疑平行趋势不成立,合成控制法直接给出了可量化的答案。作者用真实案例拆解了选择偏差,61%的政策归因比例比拍脑袋的28%靠谱多了。不过实操中MSPE阈值和权重解释还是需要经验,建议搭配安慰剂检验一起用。
我们市场部经常被销售说补贴效果显著,但看到文章里剥离出11%自然增长后,我意识到很多决策其实是基于偏差数据。合成控制法让“事后评估”变严谨了,尤其是那个“事前预测”场景,我们计划开新店时,可以用它来模拟不开店的结果,避免盲目跟风。
从学术角度看,这篇文章把合成控制法讲得比教科书更接地气。DID的平行趋势假设在现实中几乎不成立,而合成控制法用加权组合构造反事实,逻辑更自洽。安慰剂检验替代传统p值也很巧妙,适合小样本场景。不过供体池选择标准(10-50个)和预测变量数量(5-10个)的建议,最好能有更多实操验证。