双重差分法(Difference in Differences DID)
简介
常用的倍差法主要包括双重倍差法和三重倍差法。双重差分法(Difference-in-difference,DID)有几种其他的称谓:倍差法、差分再差分等
应用场景
主要是应用于在混合截面数据集中,评价某一事件或政策的影响程度。
基本思路
- 将调查样本分为两组,一组是政策或工程作用对象即“作用组”,一组是非政策或工程作用对象即“对照组”。
- 根据作用组和对照组在政策或工程实施前后的相关信息,可以计算作用组在政策或工程实施前后某个指标(如收入)的变化量(收入增长量),同时计算对照组在政策或工程实施前后同一指标的变化量。然后计算上述两个变化量的差值(即所谓的“倍差值”)。
假定
- 假定1:“平行趋势假定”(parallel trend assumption)。DID最为重要和关键的前提条件:共同趋势(Common Trends),两组之间可以存在一定的差异,但是双重差分方法要求这种差异不随着时间产生变化,也就是说,处理组和对照组在政策实施之前必须具有相同的发展趋势。这是DID的最大优点,即可以部分地缓解因 “选择偏差”(selection bias)而导致的内生性(endogeneity)
- 假定2:暂时性冲击与政策虚拟变量不相关。这是保证双向固定效应为一致估计量(consist estimator)的重要条件。在此,可以允许个体固定效应与政策虚拟变量相关(可通过双重差分或组内变换消去,或通过LSDV法控制)。
模型构造

操作实例
1、读入所需数据,生成政策前后以及控制组虚拟变量,并将它们相乘产生交互项
法1
use "http://dss.princeton.edu/training/Panel101.dta", clear
gen time = (year>=1994) & !missing(year) //设置虚拟变量,政策执行时间为1994年
gen treated = (country>4) & !missing(country) //生成地区的虚拟变量
gen did = time*treated //产生交互项
reg y time treated did, r //随后将这三个变量作为解释变量,y作为被解释变量进行回归
did的系数显著为负,表明政策实施对Y有显著的(10%显著性水平下)负效应
法2 diff命令
ssc install diff // 下载外部命令
diff y, t(treated) p(time)
/* diff命令的语法格式:
diff outcome_var [if] [in] [weight] ,[ options]
“outcome_var”表示结果变量
option中有两个必选:
“treat(处理变量) ” (0: controls; 1:treated)
“period(实验期虚拟变量)”(1=实验期,0=非实验期)
其他option
cov(varlist),协变量,加上kernel可以估计倾向得分
kernel, 执行双重差分倾向得分匹配
id(varname),kernel选项要求使用
qdid(quantile),执行分位数双重差分
pscore(varname) 提供倾向得分
logit,进行倾向得分计算,默认probit回归
ddd(varname),三重差分
*/
双重差分稳健性检验
在介绍完DID的基本思想和模型设定后,我们再来说说DID的稳健性检验,也就是要想办法证实所有效应确实是由政策实施所导致的。
所谓共同趋势或者平行趋势,是指处理组和控制组在政策实施之前必须具有相同的发展趋势。
如果不满足这一条件,那么两次差分得出的政策效应β就不完全是真实的政策效应,其中有一部分是由处理组和控制组本身的差异所带来的。如果平行趋势假设成立,那么在政策时点之前,处理组和控制组应该不存在显著差异。
时间趋势图
绘制处理组和控制组的y的均值的时间趋势
事件研究法
生成年份虚拟变量YEARj与处理组虚拟变量treati的交互项,加入模型中进行回归(M、N分别表示政策前和政策后的期数),那么交互项treatixYEARj的系数δj衡量的就是第j期处理组和控制组之间的差异。
1、生成年份虚拟变量与实验组虚拟变量的交互项,此处选在政策前后各3年进行对比。
gen period = year - 1994
forvalues i = 3(-1)1{
gen pre_`i' = (period == -`i' & treated == 1) }
gen current = (period == 0 & treated == 1)
forvalues j = 1(1)3{
gen time_`j' = (period == `j' & treated == 1)
}
2、随后将这些交互项作为解释变量进行回归,并将结果储存在reg中以备后续检验。
xtreg y time treated pre_* current time_* i.year, fe
est sto reg
3、采用coefplot命令进行绘图
coefplot reg, keep(pre_\* current post_\*) vertical recast(connect) yline(0) xline(3, lp(dash))
结果发现系数在政策前的确在0附近波动,而政策后一年系数显著为负,但很快又回到0附近。这说明实验组和控制组的确是可以进行比较的,而政策效果可能出现在颁布后一年,随后又很快消失。
安慰剂检验
即使通过了平行趋势检验,也要考虑政策干预时点之后处理组和对照组趋势的变化是否受到了其他政策或者随机性因素的影响,此时,安慰剂检验可以帮助我们的DID估计结果更具稳健性,它也是DID方法最难的部分。
安慰剂检验核心思想就是虚构处理组或者虚构政策时间进行估计,如果不同虚构方式下的估计量的回归结果依然显著,那么就说明说明原来的估计结果很有可能出现了偏误,我们的被解释变量y的变动很有可能是受到了其他政策变革或者随机性因素的影响。
在现有的政策性评估文章中,有很多种进行安慰剂检验的方法。具体如下所述。
-
第一种,可以采用政策发生之前的数据。将政策实施前的除第一年之外的所有年份“人为地”设定成为处理组的政策实施年份,然后根据DID模型逐年回归。当所有回归中的交互项系数都不显著时,说明通过了安慰剂检验,表明之前识别的政策平均效应是可靠的,否则就是不可靠的。如果政策实施前有n年数据,那么就要做n-1次上述回归。
-
第二种,可以“人为地”随机选择政策实施对象(处理组),然后使用全样本做DID回归。如果交互项系数不显著,则判断政策对随机选择的处理组都不存在政策效应,可以进一步证明之前识别的政策平均效应结果是可靠稳健的
-
第三种,改变被解释变量,通常选择理论上不受政策影响的其他变量,保持真实的对照组和处理组、真实的政策实施时间,重新进行DID 回归,理想的结果是,该政策的实施对其他被解释变量都不存在政策效应。
安慰剂检验方法1
论文1、“一带一路”倡议促进了中国高质量出口吗——来自微观企业的证据
***********************
**附表3:平行趋势检验**
***********************
set more off
gen Dyear= _日期-2014
gen pre4= (Dyear==-4&ydyl==1)
gen pre3= (Dyear==-3&ydyl==1)
gen pre2= (Dyear==-2&ydyl==1)
gen pre1= (Dyear==-1&ydyl==1)
gen current=(Dyear==0&ydyl==1)
gen post1= (Dyear==1&ydyl==1)
reghdfe ln_quality pre4 pre3 pre2 current post1 $x3, absorb(i._日期 _企业编码) vce(cluster province)
outreg2 using wjx1.doc,keep( pre4 pre3 pre2 current post1) replace addtext(Firm FE, Yes, Year FE, Yes, Controls*t, Yes, Controls*t*t, Yes, Controls*t*t*t, Yes) dec(4)
est store Dynamic1
***********************************
**图1:双重差分模型的平行趋势检验**
***********************************
coefplot Dynamic1, ///
keep(pre4 pre3 pre2 current post1) ///
coeflabels(pre4 = 2010 ///
pre3 = 2011 ///
pre2 = 2012 ///
current = 2014 ///
post1 = 2015 ) ///
vertical ///
yline(0,lp(dash)) ///
ytitle("ln(Quality)回归系数") ///
xtitle("年份") ///
addplot(line @b @at) ///
ciopts(recast(rcap)) ///
rescale(100) ///
ylabel(, nogrid) ///
scheme(tufte)
graph export "figurename.png", replace
*******************
**图2:安慰剂检验**
*******************
cd C:\Users\user\Desktop\数据\placebo
set more off
forvalues i=1(1)500 {
use dodata,clear
save ydyl_data,replace
use ydyl_data,clear
keep citycode _日期
bysort citycode _日期: gen temp_code=_n
keep if temp_code==1
drop temp_code
drop if _日期==2010
save dummy_data,replace
use dummy_data,clear
** create the false dataset
bysort _日期: keep if _n==1
sample 1, count
keep _日期
save temp,replace
use dummy_data,clear
merge m:1 _日期 using temp
keep if _merge==3
drop _merge
sample 36, count
keep _日期 citycode
rename _日期 ydyl_日期
save ydyl_time,replace
* Generate the false_ydyl_after variable
use ydyl_time
merge 1:m citycode using ydyl_data
gen false_citycode=(_merge==3)
drop _merge
egen tt=mean(ydyl_日期)
replace ydyl_日期=tt
drop tt
gen false_after=(_日期-ydyl_日期>=0)
gen false_ydyl_after=false_citycode*false_after
save ydyl_data,replace
* Regression
reghdfe ln_quality false_ydyl_after Capital_City_t Yangtz_City_t ratio_fiscal_t ratio_gdp_t lnstudent_t ratio_city_t Capital_City_t2 Yangtz_City_t2 ratio_fiscal_t2 ratio_gdp_t2 lnstudent_t2 ratio_city_t2 Capital_City_t3 Yangtz_City_t3 ratio_fiscal_t3 ratio_gdp_t3 lnstudent_t3 ratio_city_t3 , absorb(i._日期 _企业编码) vce(cluster province)
parmest,format (estimate min95 max95 %8.2f p %8.3f) saving("temp.dta", replace)
use "temp.dta", clear
keep if parm=="false_ydyl_after"
append using "ydyl_simulations.dta"
save "ydyl_simulations.dta", replace
}
erase "temp.dta"
use "ydyl_simulations.dta", clear
drop if estimate==.
save "ydyl_simulations.dta", replace
**Graphs
*Density Plot
dpplot estimate,xline(0.129) xtitle("虚假估计系数") ytitle("估计系数密度分布") saving("PDF_ydyl_dpplot.gph", replace)
