news 2026/11/3 11:27:16

DID实战指南:从平行趋势检验到PSM-DID的Stata全流程解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DID实战指南:从平行趋势检验到PSM-DID的Stata全流程解析

1. 双重差分法(DID)基础与核心逻辑

双重差分法(Difference-in-Differences,DID)是政策评估中最常用的因果推断方法之一。它的核心思想是通过比较处理组和对照组在政策实施前后的变化差异,来识别政策的净效应。这种方法巧妙地将时间维度(政策前后)和组别维度(处理组与对照组)结合起来,有效控制了时间趋势和组间固有差异的影响。

我第一次接触DID是在评估某地区最低工资政策对就业的影响时。当时发现,单纯比较政策前后就业率的变化会忽略经济周期等外部因素,而直接比较处理组和对照组的差异又无法排除地区固有特征的影响。DID通过双重差分完美解决了这个问题。

DID的基本模型可以表示为:

y_it = α + γD_t + βx_it + u_i + ε_it

其中:

  • y_it是个体i在时期t的结果变量
  • D_t是时间虚拟变量(政策后=1,政策前=0)
  • x_it是处理状态虚拟变量(处理组且在政策后时期=1,其他=0)
  • u_i是个体固定效应
  • ε_it是随机误差项

β就是我们关心的政策效应估计量。通过这个模型,我们可以分离出政策实施的净效应,而不是简单地将所有变化都归因于政策。

2. 平行趋势检验:DID的前提条件

平行趋势假设是DID方法成立的关键前提,它要求在没有政策干预的情况下,处理组和对照组的结果变量随时间变化的趋势应该是一致的。换句话说,政策实施前两组的趋势应该是平行的。

在实际操作中,我经常遇到学生问:"如果平行趋势不成立怎么办?"我的经验是,可以通过以下几种方式检验和处理:

  1. 图形法检验:绘制处理组和对照组在政策前后的时间趋势图
egen mean_y = mean(fte), by(t treated) graph twoway (connected mean_y t if treated==1, sort(t)) /// (connected mean_y t if treated==0, sort(t)), /// ytitle("全职雇员人数") xtitle("时期") /// legend(label(1 "处理组") label(2 "控制组"))
  1. 动态效应检验:加入政策前后的交互项
gen pre3 = (year == policy_year-3) gen pre2 = (year == policy_year-2) gen post1 = (year == policy_year+1) // 以此类推... xtreg y i.treated##(c.pre3 c.pre2 c.current c.post1 c.post2), fe vce(cluster id)

如果政策前的系数不显著,则支持平行趋势假设。我在一次区域政策评估中发现,加入这些动态项后,政策前的系数确实不显著,这让我对分析结果更有信心。

3. PSM-DID:解决样本选择偏差

当处理组和对照组在政策前存在系统性差异时,简单的DID估计可能会有偏差。这时可以结合倾向得分匹配(PSM)和DID,即PSM-DID方法。这种方法先通过PSM找到与处理组相似的控制组样本,再进行DID分析。

实际操作中,PSM-DID分为三个关键步骤:

  1. 估计倾向得分:通常使用logit或probit模型
psmatch2 treated x1 x2 x3, logit neighbor(4) caliper(0.05)
  1. 平衡性检验:确保匹配后协变量在处理组和对照组间平衡
pstest x1 x2 x3, both graph
  1. 进行DID分析:仅使用匹配后的样本
diff y, t(treated) p(post) kernel id(id) logit cov(x1 x2 x3)

需要注意的是,PSM-DID要求满足"条件独立性假设"和"重叠假设"。我曾在一个项目中遇到协变量太少导致匹配效果不佳的情况,这时需要考虑收集更多协变量或采用其他方法。

4. 安慰剂检验:验证结果的稳健性

安慰剂检验是验证DID结果可靠性的重要手段,核心思想是通过虚构处理组或政策时间,检验是否能得到显著的政策效应。如果虚构情况下也能得到显著结果,说明原始结果可能存在问题。

常用的安慰剂检验方法包括:

  1. 随机分配处理组:重复多次随机生成处理组
mat b = J(500,1,0) mat se = J(500,1,0) mat p = J(500,1,0) forvalues i=1/500 { use data.dta, clear sample N_treated, count // N_treated为真实处理组数量 keep id merge 1:m id using data.dta gen placebo_treat = (_merge==3) gen placebo_did = placebo_treat*post reg y placebo_did, vce(cluster id) mat b[`i',1] = _b[placebo_did] mat se[`i',1] = _se[placebo_did] mat p[`i',1] = 2*ttail(e(df_r), abs(_b[placebo_did]/_se[placebo_did])) }
  1. 改变政策时间:将政策时间提前,检验"伪政策"效应

  2. 替换结果变量:使用理论上不应受政策影响的变量进行检验

在我的经验中,安慰剂检验通过并不意味着结果绝对可靠,但不通过则强烈暗示存在问题。曾有一个项目,安慰剂检验显示随机处理组也能得到显著结果,后来发现是模型设定有问题。

5. Stata全流程操作指南

下面以一个完整的案例展示DID分析在Stata中的实现流程,使用经典的Card和Krueger(1994)数据集,研究新泽西州最低工资提高对快餐业就业的影响。

  1. 数据准备与描述统计
use cardkrueger1994.dta, clear describe summarize fte treated t bk kfc roys
  1. 基础DID回归
gen did = treated*t reg fte did treated t bk kfc roys, r
  1. 使用diff命令
ssc install diff diff fte, t(treated) p(t) cov(bk kfc roys) robust
  1. 多期DID与平行趋势检验
// 生成年度虚拟变量 tab year, gen(yr_) // 生成年度交互项 forvalues i=1/4 { gen did_yr`i' = treated*yr_`i' } xtreg fte did_yr*, fe vce(cluster id)
  1. PSM-DID实现
// 倾向得分匹配 psmatch2 treated bk kfc roys, logit neighbor(4) caliper(0.1) // DID分析 diff fte, t(treated) p(t) kernel id(id) logit cov(bk kfc roys) support
  1. 安慰剂检验
// 随机处理组安慰剂检验 preserve mat b = J(500,1,0) mat p = J(500,1,0) forvalues i=1/500 { use cardkrueger1994.dta, clear keep if t==0 sample 326, count // 处理组样本量 keep id merge 1:m id using cardkrueger1994.dta gen placebo_treat = (_merge==3) gen placebo_did = placebo_treat*t reg fte placebo_did bk kfc roys, r mat b[`i',1] = _b[placebo_did] mat p[`i',1] = 2*ttail(e(df_r), abs(_b[placebo_did]/_se[placebo_did])) } // 绘制结果 svmat b, names(coef) twoway (kdensity coef1), xline(2.935) // 2.935为真实估计值 restore

6. 常见问题与解决方案

在实际应用中,我遇到过各种DID分析的问题,以下是几个典型问题及解决方法:

  1. 平行趋势不成立怎么办?
  • 尝试加入组别特定时间趋势
  • 考虑使用三重差分法(DDD)
  • 改用合成控制法
  1. 处理效应异质性如何处理?
  • 分样本回归
  • 加入处理变量与协变量的交互项
  • 使用分位数DID
  1. 多期DID如何处理?
  • 采用事件研究法设定
  • 使用堆叠DID(stacked DID)
  • 考虑交错DID(staggered DID)的最新方法
  1. 小样本问题
  • 使用精确检验
  • 考虑置换检验(permutation test)
  • 使用bootstrap标准误

记得在一次省级政策评估中,平行趋势检验勉强通过但不够理想。我通过加入地区特定时间趋势,使结果更加稳健。这提醒我们,方法要灵活运用,不能生搬硬套。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 8:04:24

基于STC89C52与L298N的智能循迹小车设计与优化

1. 智能循迹小车的基础搭建 第一次做智能小车时,我对着满地零件发愁——电机、轮子、电路板散落一地,就像乐高缺了说明书。其实核心就三部分:STC89C52单片机是大脑,L298N是肌肉,红外传感器是眼睛。先说最关键的硬件选…

作者头像 李华
网站建设 2026/11/1 12:34:12

RexUniNLU零样本NLP系统快速上手:3步完成NER/情感/事件抽取全流程

RexUniNLU零样本NLP系统快速上手:3步完成NER/情感/事件抽取全流程 1. 这不是另一个“调参工具”,而是一站式中文语义理解入口 你有没有遇到过这样的情况:刚写完一段新闻稿,想立刻知道里面提到了哪些公司、谁赢了比赛、情绪是正面…

作者头像 李华
网站建设 2026/11/2 8:04:24

深度解析:如何通过 MQTT 与物理感知实现老旧货梯的机器人梯控联动

摘要: 存量电梯的智能化改造是工业互联网领域公认的“硬骨头”。老旧货梯协议封闭、布线杂乱,使得基于软件协议的对接方式几乎失效。西门子等传统PLC方案虽然稳定但开发灵活性差;全云端方案在弱网环境下风险巨大。本文将从协议交互、边缘感知…

作者头像 李华
网站建设 2026/11/2 8:04:24

SDXL-Turbo实战教程:本地一键部署实现打字即出图的实时绘画

SDXL-Turbo实战教程:本地一键部署实现打字即出图的实时绘画 1. 为什么你需要“打字即出图”的绘画体验? 你有没有过这样的时刻:脑子里刚冒出一个画面,手却还卡在写提示词的第三步——反复删改“cyberpunk”要不要加连字符&#…

作者头像 李华
网站建设 2026/11/2 23:50:46

用SGLang轻松实现复杂LLM程序,无需深度技术背景

用SGLang轻松实现复杂LLM程序,无需深度技术背景 你是否曾被这些场景困扰:想让大模型完成多轮任务规划,却卡在状态管理上;需要模型输出严格JSON格式,却反复调试正则约束;想调用外部API再综合推理&#xff0…

作者头像 李华