如何用DID做一份简单的毕业论文实证 您所在的位置:网站首页 通灵之术表情包召唤 如何用DID做一份简单的毕业论文实证

如何用DID做一份简单的毕业论文实证

2022-12-31 21:00| 来源: 网络整理| 查看: 265

小郑的毕业论文实证方法小结

明明21年才刚交完本科毕业论文,22年就又写了一次毕业论文 。21年完成本科毕业论文初稿后写了一篇“面板数据分析”的推文(其实是笔记),22年硕士毕业论文初稿完成了,想着怎么也得再整一篇。所以说干就干,这两天汇总了一篇关于DID的小结。

前排甩锅提示:本人小小专硕,才疏学浅,本篇主要为自己写论文期间琢磨的代码小结,主要参考了连玉君老师的“连享会”公众号推文,我导师方红生教授《面板数据分析与Stata应用》课程的课堂代码,以及“功夫计量经济学”公众号部分推文,若整理内容有错误,恳请大佬评论指出。

划重点:“小郑摸鱼笔记”公众号后台回复“双重差分”可获取完整“DO文档”。

DID全名difference-in-differences,即双重差分法,是实证研究中一种常用的政策效应评估方法。它的识别策略为先观察受政策影响的个体在政策前后的变化,再观察未受政策影响的个体在政策前后的变化,而两个变化之间的差异就是政策干预对个体的影响。关于DID的基本理论,网上搜一搜有很多,本文就不过多阐述了,下面主要写一写怎么在Stata用DID做一份政策效应评估。

Part1 基准回归结果的输出与展示

本文主要使用reghdfe命令估计一个双重差分模型并报告最终结果,同时介绍如何进一步确保自己的结果可信以及如何检验背后的作用机制和异质性。reghdfe主要用于实现多维固定效应线性回归,由于其使用依赖于最新版的gtools命令,所以安装时我们需要同时安装两者。

ssc install gtools, replace //安装最新版命令 ssc install reghdfe, replace // 安装最新版命令

reghdfe的语法如下。

reghdfe depvar [indepvars] [if] [in][weight], absorb(absvars) [options]

depvar:被解释变量。

indepvars:解释变量,核心解释变量和控制变量都放在这里。

absorb(absvars):引入固定效应,注意absvars一般代表一些数值型编号,比如企业编号、年份、省份编号、行业编号、官员类型编号等等,不同类型固定效应的交互项之间用#连接即可。

options:这部分可以通过help reghdfe获取命令的帮助文档,里面有具体说明。

举例:以lnp为被解释变量,did为双重差分的核心解释变量,controlvar1和controlvar2为控制变量估计一个双重差分模型,估计标准误采用企业层面的聚类稳健标准误。对于使用到的连续型变量,如果有异常值,可以先用winsor2命令进行缩尾处理。

ssc install winsor2 winsor2 controlvar1 controlvar2, cut(1,99) replace by(Accper)

先生成政策虚拟变量,birth_date表示受政策干预的样本受到干预的时间,单期DID下就是固定的政策发生时间。

gen did = (Accper >= birth_date)

不加入控制变量,不控制任何固定效应,将结果储存在m1中。

xtreg lnp du dt did, vce(cluster Stkcd) //vce(cluster Stkcd) 表示将标准误聚类到Stkcd(企业个体) estimates store m1

加入控制变量,不控制任何固定效应,将结果储存在m2中。

xtreg lnp du dt did controlvar1 controlvar2, vce(cluster Stkcd) estimates store m2

控制个体固定效应(Stkcd表示企业编号)和年份固定效应(Accper表示年份),将结果储存在m3中。

reghdfe lnp did controlvar1 controlvar2, absorb(Stkcd Accper) vce(cluster Stkcd) estimates store m3

控制个体固定效应、年份固定效应与省份固定效应(provincecode)交互项、年份固定效应与行业固定效应(industrycode)交互项,将结果储存在m4中,注意由于后面新加了两个与年份固定效应有关的交互项,前面可以删除年份固定效应。

reghdfe lnp did controlvar1 controlvar2, absorb(Stkcd Accper#provincecode Accper#industrycode) vce(cluster Stkcd) estimates store m4

上面每一次回归结果报告的内容里面是不显示固定效应的,要使报告结果中自动添加固定效应,可以使用reghdfe附带的一个命令estfe,该命令允许固定效应以 Stkcd FE = Yes/NO 的形式呈现在最终的回归结果中。但在使用estfe命令前,我们需要安装erepost命令,该命令在执行estfe命令时将会用到。

findit erepost estfe m*, labels(Stkcd "个体固定效应" Accper "年份固定效应" Accper#icode "年份*行业固定效应" Accper#pcode "年份*省份固定效应") return list

最后通过esttab命令呈现汇总结果,star表示显著性水平的显示标准,ar2表示报告调整的R方。

esttab m*, indicate("控制变量=controlvar1 controlvar2" `r(indicate_fe)') star(* 0.1 ** 0.05 *** 0.01) ar2

也可以通过reg2docx命令将结果导出到word。注意,此命令和esttb一次只能选择一条在return list后面执行。

reg2docx m1 m2 m3 m4 using 基准回归结果.docx, ///将结果储存在基准回归结果.docx中 replace indicate("控制变量=controlvar1 controlvar2" `r(indicate_fe)') ///将控制变量和固定效应以YES/NO的形式显示 drop(controlvar1 controlvar2) ///不汇报controlvar1和controlvar2的估计结果 scalars(N r2(%9.3f) r2_a(%9.2f)) ///汇报样本量、R方和调整的R方 star(* 0.1 ** 0.05 *** 0.01) ///设置汇报的显著性水平打星标准Part2 平行趋势检验与绘图

Step1:生成相对的时间值。

gen event = Accper-birth_date

Step2:对实施新政较晚和政策发生后较久的个体进行政策前后的截尾处理(可选)。

replace event = -4 if event < -4 replace event = 4 if event > 4

Step3:生成时间相对虚拟变量eventt。

tab event, gen(eventt)

Step4:将一直处于控制组的个体的eventt*的值全部赋值为0。

forvalues i=1/4{ replace eventt`i'=0 if eventt`i' ==. }

Step5:将首期作为基准对照组。

drop eventt1

Step6:数据处理完毕,进行平行趋势检验。

reghdfe lnp eventt* controlvar1 controlvar2, absorb(Stkcd Accper#provincecode Accper#industrycode) vce(cluster Stkcd)

Step7:绘图,coeflabels的标签需要根据自己的数据重新赋值,其余参数可以不修改。

coefplot, keep(eventt*) ///保留指定系数 coeflabels(eventt2=-3 eventt3=-2 eventt4=-1 eventt5=0 eventt6=1 eventt7=2 eventt8=3 eventt9=4) ///根据eventt*设置横轴的政策发生相对时间 levels(90) vertical lcolor(black) /// msymbol(O) msize(small) mcolor(navy) /// addplot(line @b @at,lcolor(navy) lwidth(medthick)) /// 各个点连线连起来 ytitle(回归系数, size(small)) /// ylabel(, labsize(small) angle(horizontal) nogrid) yline(0, lwidth(vthin)lpattern(solid) lcolor(black)) /// xtitle(政策实施相对时间, size(small)) /// xlabel(,labsize(small)) graphregion(fcolor(white) lcolor(white) ifcolor(white) ilcolor(white)) /// ciopts(recast(rcap)) xline(10.5, lwidth(vthin) lpattern(solid)lcolor(black)) /// graphregion(color(white)) //白底

实操上我们认为平行趋势通过的条件:政策发生前的eventt2-eventt4均不显著。但实际上,由于处理组个体在处理时点后的反事实结果(处理组没有接受处理的Y)无法观察到,平行趋势假设本质上是无法直接检验的。因此,研究者通常退而求其次,通过检验可观察的处理组和控制组事前趋势是否相同来间接地检验平行趋势假设。如果处理组和控制组的事前趋势平行,那么研究者就有一定的信心认为事后趋势也是平行的。

平行趋势没有通过怎么办:

(1)在DID变量的基础上乘一个空间变量构造三重差分,摆脱对平行趋势的依赖;

(2)构造PSM-DID或者SDID;

(3)对于政策发生前的eventt*系数是否整体显著进行F检验(Suarez & Zidar,2016;刘志阔、陈钊、吴辉航等,2019)。

Part3 稳健性检验

这部分主要就是为了证明基准回归的结果在排除种种误差的干扰后仍然是成立的,常见的误差分析方向有:

(1)同期干扰政策排除,就是把同期发生的一些能够对被解释变量产生相同作用方向的政策一一加以排除,具体策略可以考虑删除受这些同期政策影响的样本,或者将可以刻画该同期政策的变量作为控制变量纳入基准回归(张克中、欧阳洁和李文健,2020);

(2)核心变量度量误差排除:更换被解释变量的度量方式;

(3)样本自选择偏差排除:可以采用PSM-DID,也可以采用SDID;

(4)安慰剂检验:就是假设这种政策冲击是随机发生的,生成一个随机政策冲击did进行基准回归,重复模拟10000次,将每次模拟后did的系数值记录下来绘制分布函数图像,观察基准回归的系数值是否落在分布之外;

(5)其他稳健性检验:视样本数据特点决定。

下面主要介绍以上几种分析方向里面的PSM-DID、SDID和安慰剂检验如何操作。

PSM-DID:首先,利用PSM方法对处理组样本进行匹配,以选择尽可能相近样本,匹配方法有有放回的一对一临近匹配、有放回的一对多最临近匹配以及核函数匹配。然后,利用匹配后样本对上文的基准结果和中间机制进行稳健性检验。因为PSM适合截面数据,而DID适合面板数据,所以PSM-DID本身存在矛盾。

PSM-DID在操作上更推荐采用逐期匹配(但这种方法并非能够完美解决PSM-DID本身的矛盾)。逐期匹配的思想:首先分年份进行匹配,然后保存每一年的匹配结果,最后合并各个年份的匹配结果。

forvalues i = 2011/2019 { use xxx.dta,clear //调用样本数据 keep if Accper==`i' set seed 20221226 //设置随机数种子确保结果可复制 gen tmp=runiform() //生成随机数 sort tmp //根据产生的随机数对样本进行排序 *核回归 psmatch2 du controlvar1 controlvar2, outcome(did) kernel ate logit common //利用 logit 模型估计倾向得分,注意outcome放入did变量,du为政策分组虚拟变量,其余为协变量 drop if _weight==. save psmdid_`i',replace } use psmdid_2011,clear forvalues i = 2012/2019 { append using psmdid_`i' }

执行上述程序后,新的数据将储存在 psmdid_2011.dta 中,直接利用该数据集进行did估计即可。

reghdfe lnp did controlvar1 controlvar2, absorb(Stkcd Accper#provincecode Accper#industrycode) vce(cluster Stkcd)

除了核回归的匹配策略,PSM在匹配时还可以使用近邻匹配、半径匹配、协变量匹配等,具体代码如下。

*近邻匹配(1:4) psmatch2 du controlvar1 controlvar2, outcome(did) n(4) ate logit ai(4) common pstest [indepvars] , both graph *半径匹配(0.01) psmatch2 du controlvar1 controlvar2, outcome(did) radius ate logit cal(0.01) common *协变量匹配,psmatch2命令的协变量匹配只能使用马氏距离测度相似性 psmatch2 du, outcome(did) mahal(controlvar1 controlvar2) n(4) ai(4) ate

合成双重差分差法SDID的基本思想是,分别给控制组个体和处理前时期赋予个体权重和时间权重,并引入固定效应,从而削弱对平行趋势假设的依赖。SDID方法不仅通过引入应用于控制组个体的个体权重,找到与处理组个体相似的控制组个体赋予更高的权重,还通过引入应用于处理前时期的时间权重,找到与处理后时期相似的处理前时期赋予更高的权重。Arkhangelsky等(2021)证明与DID和SC相比,SDID方法在实证上具有更强的稳健性和更高的估计量精度。

SDID估计命令的语法如下。

sdid Y S T D [if] [in], vce(method) seed(#) reps(#) covariates(varlist [, method]) graph g1_opt(string) g2_opt(string) unstandardized graph_export([stub] , type)

Y:产出变量,只能是数值型。

S:个体变量,可以是数值型或字符串。

T:时间变量,只能是数值型。

D:处理变量,当个体被处理时取值为 1,否则取值为 0。

vce(method):有三种计算标准误的方法,即 bootstrap、jackknife、placebo。

covariates(varlist [, method]):用来调整Y的控制变量,调整方法有两种。一种是 Arkhangelsky 等提出的 optimized (默认),另一种是 Kranz (2021) 提出的 projected,后者运算速度要更快。

graph:指定这一选项将会绘制出第 2 部分图形。

ssc install sdid, replace // https://github.com/Daniel-Pailanir/sdid drop if controlvar1 ==. drop if controlvar2 ==. ssc install xtbalance xtbalance, range(2011 2019) //获得平衡面板数据集 sdid lnp Stkcd Accper did, vce(bootstrap) seed(1213) graph graph_export(profit,.png) covariates(controlvar1 controlvar2)

安慰剂检验的permute命令语法如下。

permute permvar exp_list [, options] : command

permvar:需要进行随机排列的变量,即 DID 中的Treat和Post的交互项。

exp_list:需要提取的统计量,一般是交互项的回归系数。

常用的options选项有。

reps(#):随机抽样的次数。

seed(#):设定随机数种子以保证结果可重复。

saving(file):将抽样结果得到的exp_list保存在file这个文件中。

command:回归命令。

reghdfe lnp did controlvar1 controlvar2, /// absorb(Stkcd Accper#industrycode Accper#provincecode) vce(cluster Stkcd) permute did _b[did],reps(10000) seed(123) saving("simulations.dta",replace) :reghdfe lnprofit did controlvar1 controlvar2, /// absorb(Stkcd Accper#industrycode Accper#provincecode) vce(cluster Stkcd) use "simulations.dta", clear #delimit ; dpplot _pm_1, xline(1.2, lc(black*0.5) lp(dash)) //设置基准回归结果的参考线x=1.2 xline(0, lc(black*0.5) lp(solid)) xtitle("Estimator", size(*0.8)) xlabel(-1(0.5)1.5, format(%4.1f) labsize(small)) //设置横坐标范围[-1,1.5],步长0.5 ytitle("Density", size(*0.8)) ylabel(, nogrid format(%4.1f) labsize(small)) note("") caption("") graphregion(fcolor(white)) ; #delimit crPart4 机制检验

在机制检验上更推荐采用联立方程法进行估计。

假设X通过M影响了Y,那么可以构造联立方程如下。

Y = αM+βX+ε

M = γX+μ

在使用单一方程估计法(比如逐步回归法)时,由于忽略了各方程之间的联系(包括各方程扰动项之间的联系),其估计结果不如将所有方程作为一个整体进行估计,即系统估计法,更有效率。最常见的系统估计方法:三阶段最小二乘法(3SLS)。系统估计法的缺点在于,如果其中某个方程估计得不准确,则可能影响系统中其他方程的估计。

对于一个多方程系统,如果各方程中都不包含内生解释变量,则对每个方程进行OLS估计(2SLS)是一致的,但却不是最有效率的,因为单一方程OLS估计忽略了不同方程的扰动项之间可能存在相关性。更有效率的系统估计方法SUR(Seemingly Unrelated Regression Estimation)。

3SLS的Stata实现

xi:reg3 (第一个方程的被解释变量 第一个方程的解释变量 i.code i.year) (第二个方程的被解释变量 第一个方程的解释变量 i.code i.year), endog(varlist) exog(varlist)

endog(varlist)表示系统内除了被解释变量外的内生变量,exog(varlist)代表从系统外找的工具变量;如果系统中没有除了被解释变量外的内生变量,那么这两个选项可以不加。

举例:三阶段最小二乘估计,假设机制变量为lev。

xi:reg3 (lev did i.Stkcd i.Accper) (lnp lev did i.Stkcd i.Accper) , endog(controlvar1 controlvar2) exog(IV1 IV2)

SUR的Stata实现。

xi:reg3 (第一个方程的被解释变量 第一个方程的解释变量 i.code i.year) (第二个方程的被解释变量 第一个方程的解释变量 i.code i.year), sure

举例:SUR估计,假设机制变量为lev。

xi:reg3 (lev did controlvar1 controlvar2 i.Stkcd i.Accper) (lnp lev did controlvar1 controlvar2 i.Stkcd i.Accper), surePart5 异质性检验

异质性,我的理解就是y与x的关系可能受到第三个变量z的大小影响而有所不同

异质性检验常见的三种策略:

(1)分组回归,注意分组变量的参考应当选取政策发生前一年的数据,比如按照政策发生前一年的size变量值将企业分成大、中、小三类企业,然后分别进行回归;

(2)将异质性变量与did变量交乘构造三重差分;

(3)面板门限模型。

面板门线模型的简单介绍(静态面板,动态略)

生活中的门限效应例子:对某一项技能的掌握程度与使用这项技能的时间可能不是线性关系,刚开始入门阶段,由于不得要领,可能再怎么使用这一技能也无法得心应手,技能掌握程度对技能使用时间不敏感;当技能使用多了后突然领悟到一些诀窍,导致技能使用变得得心应手,这个时候随着技能使用时间的增加,对这一技能的理解也逐渐增加,越用越娴熟。

安装门限效应估计命令xthreg(stata14及以上)。

findit xthreg xtbalance, range(2011 2019) //xthreg只能用于平衡面板数据 set seed 20221226 //设置一个随机数种子,为了使得接下来xthreg中自助法的随机抽样可重现

xthreg的语法如下。

xthreg y z1 z2 z3 z4, rx(x) qx(t) thnum(1) bs(300) trim(0.01) grid(100) r

y:被解释变量。

z1-z4:协变量(控制变量)。

rx(#)):里门限被解释变量(依赖于异质性因素的核心解释变量)。

qx(#):里门限解释变量(异质性变量)。

thnum(#):门槛个数。

bs(#):自举次数(理论上越多越好,但是考虑到效率,一般设置成300以上)。

trim(#):门限分组内异常值去除的比例(一般选0.01或0.05)。

grid(#):样本网格计算的网格数(一般设置成100或300)。

r:用聚类稳健标准误。

*单门限模型 xthreg lnp controlvar1 controlvar2 i.Accper, rx(did) qx(size) thnum(1) bs(300) trim(0.01) grid(400) r *-画出门限真实性检验的置信区间图像(LR图) _matplot e(LR), columns(1 2) yline(7.35, lpattern(dash)) connect(direct) /// msize(small) mlabp(0) mlabs(zero) ytitle("LR Statistics") xtitle("Threshold") /// recast(line) name(LR) *三门限 xthreg lnp controlvar1 controlvar2 i.Accper, rx(did) qx(size) thnum(3) grid(400) trim(0.01 0.01 0.05) bs(0 300 300) thgive //thgive选项能够直接在之前的单门限估计结果上进行多门限的估计,更为快速 xthreg lnp controlvar1 controlvar2 i.Accper, rx(did) qx(size) thnum(3) grid(400) trim(0.01 0.01 0.05) bs(0 300 300) *-前两个门限置信区间的LR图 _matplot e(LR21), columns(1 2) yline(7.35, lpattern(dash)) connect(direct) msize(small) /// mlabp(0) mlabs(zero) ytitle("LR Statistics") xtitle("First Threshold") recast(line) name(LR21) nodraw //nodraw不画出图像,去掉就会画出 _matplot e(LR22), columns(1 2) yline(7.35, lpattern(dash)) connect(direct) msize(small) /// mlabp(0) mlabs(zero) ytitle("LR Statistics") xtitle("Second Threshold") recast(line) name(LR22) nodraw graph combine LR21 LR22, cols(1) *-第三个门限置信区间的LR图 _matplot e(LR3), columns(1 2) yline(7.35, lpattern(dash)) connect(direct) msize(small) /// mlabp(0) mlabs(zero) ytitle("LR Statistics") xtitle("Third Threshold") recast(line) name(LR3) *双门限 xthreg lnp controlvar1 controlvar2 i.Accper, rx(did) qx(size) thnum(2) grid(400) trim(0.01 0.01) /// bs(0 0) xthreg lnp controlvar1 controlvar2 i.Accper, rx(did) qx(size) thnum(2) grid(400) trim(0.01 0.01) /// bs(300 300)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有