(自学笔记11-A)让我们重新认识一下吧,双重差分!

以下内容并非原创,主要来源于各大学术公众号、b站等,仅用于本人学术记录,侵删。

计划自学笔记11分为A和B两部分,A部分简要梳理双重差分的理论和原理,B部分从实证角度对DID的代码和应用进行梳理。

最基本的DID形式与概念

  假设有两个城市A和B,在T=0时期,这两座城市的发展趋势没有什么差异,此时,政府将城市A设立为低碳试点城市,在T=1时期,城市A相较于城市B的环境污染情况出现了差异。去捕捉变化的方法叫作双重差分。

  双重差分依赖于准自然实验,实验的处理效应是参与实验的个体参与试验后的结果减去其如果不参与实验后的结果。即:

E[y1y0D=1]=E[y1D=1]E[y0D=1]E[y_1-y_0|D=1]=E[y_1|D=1]-E[y_0|D=1]

  而此时,反事实的结果(不参与实验的结果)现实当中是观察不到的。DID的思路就是:寻找一个合意的控制组。合成控制法的思路是:拟合一个反事实结果。

DID的适用条件

  DID的处理效应:用实验组个体参与实验后的结果减去控制组个体不参与实验后的结果:

E[Δy1D=1]E[Δy0D=0]=E[Δy1D=1]E[Δy0D=1]+E[Δy0D=1]E[Δy0D=0]E[\Delta{y_1}|D=1]-E[\Delta{y_0}|D=0]=E[\Delta{y_1}|D=1]-E[\Delta{y_0}|D=1]+E[\Delta{y_0}|D=1]-E[\Delta{y_0}|D=0]

分组随机且组间可比

  满足平行趋势(给定分组,两组之间具有平行趋势)

  分组自选择性弱(随便如何分组,这种平行趋势都存在)

  组间异质性尽量小(平行趋势不仅仅是均值的平行)

分组后没有溢出效应

  例如,城市A和城市B之间,不存在着污染的跨区域流动。(这里我想到当初模仿数经上面一个DID论文,他的卖点恰好就是放松了DID溢出效应的设定,也就是将受到政策冲击组的邻近城市作为实验组,去检验DID的溢出效应。不知道这样做是否合理?)

DID适用性的检验

  对于单期DID,最直观的方式就是平行趋势的画图!画的是分组的E[Y]或者E[残差项]

  对于多期DID,其平行趋势检验应用了事件研究法,也就是将时间变量设定为虚拟变量

  安慰剂检验:构造伪政策冲击时间、或者伪实验组

  分组自选择性检验:只用实验期前的数据进行回归,理想情况下系数不显著。

  其他方法:工具变量、Heckman两步法、机器学习等。

DID形式的拓展

  广义DID(连续DID):个体同时受政策影响,但影响程度不同。这种设定可以讨论没有控制组的情况,但是只保留了DID的形式(针对全面铺开的政策)。另外也有文章对影响程度进行了人为的划分,进而分出实验组和控制组,这种主观性较强,需要更多的稳健性检验。

  多期DID(目前大多数,也是被研究最多的DID形式):实验组受政策影响的时间是不同的。

  PSM-DID:解决组间可比的问题(样本差异不要过大),解决分组自选择的问题,感觉目前多数作为稳健性检验去做。

  RD-DID:某些时候不能用PSM,因为出现了根据某一个X,实验组的样本参与实验的概率都是1,控制组参与实验的概率都是0的现象,也就是断点回归。

多期双重差分的研究进展

这里的“多期”是指政策冲击时间的多期,也就是交叠DID,“单期”是指政策冲击时间的唯一,也就是传统的DID。

单期DID与多期DID的估计结果差异

案例和代码来自许文立老师宏观研学会公众号

对于受到相同时间政策冲击的实验组来说,可以建立这样一个简单的stata数据集。该数据集由一个控制组和两个实验组构成,并且两个实验组受到的政策冲击影响不同。

`DID*********************************************** 同时处理,但处理强度不同
clear      // 清除stata已存在的数据
local units = 3
local start = 1
local end   = 20
local time = `end' - `start' + 1
local obsv = `units' * `time'
set obs `obsv'
egen NU     = seq(), b(`time')  
egen Period = seq(), f(`start') t(`end')   
sort NU Period
xtset NU Period    // 声明面板数据类型
lab var NU "Panel variable"
lab var Period  "Time  variable"
* 假设在第5期之后,有新校区假设
* 创建处理变量T和结果变量y
gen T = 0
replace T = 1 if NU>=2 & Period>=5    //处理发生在第二和三个id,第5期,这时T=1,其它所有情况T=0
lab var T "Treated"
cap drop Y
gen Y = 0
replace Y = cond(T==1, 2, 0) if NU==2
replace Y = cond(T==1, 4, 0) if NU==3
lab var Y "Outcome variable"  
twoway (connected Y Period if NU==1) (connected Y Period if NU==2) (connected Y Period if NU==3)  ,  xline(4.5) xlabel(1(1)20)     legend(order(1 "NU=1" 2 "NU=2" 3 "NU=3"))
* 面板数据回归
xtreg Y T Period,fe    
reghdfe Y T, absorb(NU Period) `

  通过stata命令可以得出平均处理效应(ATT)为3,即2和3的处理效应的平均值,在最终的ATTA里,两个处理组的权重都是0.5。这是没有假如个体固定效应和时间固定效应的ATT,当假如了控制变量,如固定效应后,再观察其结果。

`* 首先,舍弃上例中生成的数据,重新来生成Y的数据cap drop Y
gen Y = 0
replace Y = NU + Period + cond(T==1, 0, 0) if NU==1
replace Y = NU + Period + cond(T==1, 2, 0) if NU==2
replace Y = NU + Period + cond(T==1, 4, 0) if NU==3
lab var Y "Outcome variable"
* 可视化数据
twoway  (connected Y Period if NU==1) (connected Y Period if NU==2)  (connected Y Period if NU==3) , xline(4.5)  xlabel(1(1)10) legend(order(1 "NU=1" 2 "NU=2" 3 "NU=3"))
*此时的ATT无法直观观察到,需要通过回归计算
reghdfe Y T, absorb(NU Period)
*可以比较不同控制情形下的结果
reg Y T        // 不控制任何因素
reg Y T i.Period      // 仅仅控制时间固定效应
reg Y T i.NU    // 仅仅控制个体固定效应
reg Y T i.Period i.NU  // 双向固定效应(正确!)

  而针对多期DID(不同处理期)来说,ATT的结果又会不一样。同样利用模拟数据进行演示:

`clear      // 清除stata已存在的数据
local units = 3
local start = 1
local end   = 20
local time = `end' - `start' + 1
local obsv = `units' * `time'
set obs `obsv'
egen NU     = seq(), b(`time')  
egen Period = seq(), f(`start') t(`end')   
sort NU Period
xtset NU Period    // 声明面板数据类型
lab var NU "Panel variable"
lab var Period  "Time  variable"
* 假设在第5期之后,有新校区假设
* 创建处理变量T和结果变量y
gen T = 0
replace T = 1 if NU==2 & Period>=5   //处理发生在第二个id,第5期,这时T=1,其它所有情况T=0
replace T = 1 if NU==3 & Period>=10   //处理发生在第三个id,第10期,这时T=1,其它所有情况T=0
lab var T "Treated"
cap drop Y
gen Y = 0
replace Y = cond(T==1, 2, 0) if NU==2
replace Y = cond(T==1, 4, 0) if NU==3
lab var Y "Outcome variable"  
twoway (connected Y Period if NU==1) (connected Y Period if NU==2) (connected Y Period if NU==3) , xline(4.5) xlabel(1(1)20) legend(order(1 "NU=1" 2 "NU=2" 3 "NU=3"))
*运行回归命令计算结果
reghdfe Y T ,absorb(NU Period)
*此时的ATT为3.21
*而考虑了个体和时间趋势下,回归后的ATT为3.29
cap drop Y
gen Y = 0
replace Y = NU + Period + cond(T==1, 0, 0) if NU==1
replace Y = NU + Period + cond(T==1, 2, 0) if NU==2
replace Y = NU + Period + cond(T==1, 4, 0) if NU==3
lab var Y "Outcome variable"
* 可视化数据
twoway (connected Y Period if NU==1) (connected Y Period if NU==2)  (connected Y Period if NU==3)  ,  xline(4.5)  xlabel(1(1)10) legend(order(1 "NU=1" 2 "NU=2" 3 "NU=3"))
reghdfe Y T ,absorb(NU Period)

  为什么呢?因为此刻处理时点发生了变化,个体2是在第五期受到处理,而个体3是在第十期受到处理。因此,就无法清晰区分出“处理前”和“处理后”,也不能很好区分“处理组”和“对照组”。例如在第5-10期,只有NU=2这个组群发生了变化,其他两个组群都保持不变。那么该如何理解ATTA=3.29这个估计值呢?这就是目前多期DID所探讨的问题。


(自学笔记11-A)让我们重新认识一下吧,双重差分!
http://wynwynwyn.xyz/2025/04/15/(自学笔记11-A)让我们重新认识一下吧,双重差分!/
作者
Wyn
发布于
2025年4月15日
许可协议