ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

新手友好:用Stata做双重差分(DID)全流程教程

新手友好:用Stata做双重差分(DID)全流程教程 想象一下2017年几座城市突然试点共享单车2020年又有一批城市跟上。你想知道共享单车到底有没有让交通更顺畅这就是经典的双重差分DID问题。本教程用一个贴近生活的例子带你从零跑通DID全流程基准回归 平行趋势 安慰剂 稳健性 异质性。一、为什么用DID一句话讲清楚我们比较两组城市处理组试点了共享单车的城市对照组一直没有试点的城市再比较试点前后的变化。DID就是把“组间差异”和“时间差异”同时扣掉剩下的就是政策净效应。简单公式政策效应 处理组试点后 − 处理组试点前 − 对照组同期变化揭开政策影响的面纱通俗解读DID模型及其在Stata中的应用附稳健性检验详解二、数据准备与DID变量精确设定假设你有一份2015–2024年城市面板数据城市 年份核心被解释变量是congestion交通拥堵指数数值越高越堵。代码如下* 设定面板结构告诉Stata这是城市-年份面板数据xtset city year* 1. 生成政策实施年份分两批试点模拟真实政策分批推进gen action .* 先生成一个空变量用来存放政策实施年份replace action 2017 if inlist(city, 杭州,成都,武汉,南京,厦门,青岛)* 第一批试点城市赋值为2017replace action 2020 if inlist(city, 西安,长沙,苏州,合肥,福州,郑州,南昌)* 第二批试点城市赋值为2020* 2. 处理组虚拟变量有政策实施年份的城市为处理组treat1否则为对照组treat0gen treat (action ! .)* action非缺失的城市就是处理组* 3. 核心DID变量处理组在政策实施当年及之后取1其余全部取0gen did (year action) if action ! .* 只对处理组生成政策当年及以后1replace did 0 if missing(did)* 对照组和所有政策前的观测全部设为0* 4. 控制变量全局宏示例按实际研究替换global controls ln_gdp ln_pop road_density bus_num rain temp* 把常用控制变量打包后面直接调用​​​​​​​* 5. 缩尾处理可选消除极端值影响foreach var in congestion $controls {winsor2 var, cuts(1 99) replace}* 对每个变量做1%和99%分位缩尾变量含义再强调一次action政策实际落地年份处理组才有值treat是否属于处理组固定不变did真正进入回归的交互项政策生效后的处理组观测三、描述性统计​​​​​​​* 整体描述统计sum congestion did $controls* 按处理组/对照组分组看均值、标准差等tabstat congestion $controls, by(treat) statistics(mean sd min max) columns(statistics)先确认处理组和对照组在政策前的基础特征差异以及样本量是否均衡。四、多重共线性检查​​​​​​​* 先跑一个不含固定效应的普通回归方便计算VIFreg congestion did $controlsestat vif* 查看方差膨胀因子一般小于10即可如果所有变量VIF都小于10说明多重共线性问题不严重可以放心进入下一步。五、基准回归双向固定效应​​​​​​​* 双向固定效应回归城市固定效应 年份固定效应标准误在城市层面聚类reghdfe congestion did $controls, absorb(city year) cluster(city)est store baseline* 把结果存起来方便后面导出* 导出漂亮的回归表格esttab baseline using 基准回归.rtf, replace b(%6.3f) se(%6.3f) star(* 0.1 ** 0.05 *** 0.01) scalar(N r2) title(基准回归共享单车对拥堵的影响) mtitle(交通拥堵指数)结果解读如果did系数显著为负说明共享单车试点后处理组城市的拥堵指数相对对照组显著下降政策产生了缓解拥堵的净效应。六、平行趋势检验最重要的前提假设政策实施前处理组和对照组的趋势必须平行。用事件研究法检验* 生成相对年份政策当年0之前为负之后为正capture drop period* 如果之前有period变量先删掉避免冲突gen period year - action if treat 1* 只对处理组计算相对年份* 获取所有实际出现的相对年份排除基期-1因为-1期作为参照组levelsof period if period ! -1 !missing(period), local(levels)* 生成事件虚拟变量负值用m前缀正值直接用数字foreach p of local levels {if p 0 {local abs abs(p)gen event_mabs (period p) * treat}else {gen event_p (period p) * treat}}* 例如event_m2表示政策前第2年event_0表示政策当年event_1表示政策后第1年* 双向固定效应回归把所有事件虚拟变量放进去reghdfe congestion event_* $controls, absorb(city year) cluster(city)* 构建rename映射让横坐标显示真实的相对年份而不是event_m2这种变量名local rename_cmdforeach p of local levels {if p 0 {local abs abs(p)local rename_cmd rename_cmd event_mabs p}else {local rename_cmd rename_cmd event_p p}}* 把event_m2映射成-2event_1映射成1方便画图时横坐标好看* 画平行趋势图coefplot, keep(event_*) vertical xlabel(, angle(45) labsize(medsmall)) yline(0, lcolor(red) lwidth(medthin) lpattern(solid)) xline(0.5, lcolor(black) lwidth(thin) lpattern(dash)) ciopts(lcolor(blue) lwidth(thin)) mcolor(black) msymbol(O) msize(medsmall) connect(l) lcolor(black) lwidth(thin) lpattern(solid) graphregion(color(white)) plotregion(margin(medium)) title(平行趋势检验, size(medium)) xtitle(政策实施相对年份, size(small)) ytitle(系数, size(small)) legend(off) rename(rename_cmd)graph export 平行趋势检验.png, as(png) replace width(1200) height(800)判断标准政策前负期系数均不显著 → 平行趋势假设成立政策后系数逐渐变负且显著 → 政策确实产生了持续影响七、安慰剂检验随机假政策​​​​​​​* 先跑真实模型提取真实系数reghdfe congestion did $controls, absorb(city year) cluster(city)local true_coef _b[did]* 把真实did系数存起来后面画图用* 创建临时文件用来存放500次随机回归的系数tempfile resultspostfile handle b using results, replace* 循环500次每次随机抽取假处理组forvalues i 1/500 {preservegen u runiform()sort ugen fake_treat 0replace fake_treat 1 in 1/13bysort city: egen treat_fake max(fake_treat)gen placebo_did (year 2017)* treat_fakequietly reghdfe congestion placebo_did $controls, absorb(city year) cluster(city)post handle (_b[placebo_did])restore}* 随机把前13个城市设为假处理组数量要和真实处理组一致* 把假处理标记扩展到该城市所有年份* 生成假DID变量统一假设从2017年开始* 安静跑回归并把假系数存进临时文件postclose handle* 打开存放假系数的数据集并画直方图use results, clearsum blocal bw (r(max) - r(min)) / 30* 自动计算合适的组距hist b, frequency width(bw) color(navy%30) lcolor(black) xline(true_coef, lcolor(red) lwidth(medthick)) xline(0, lcolor(black) lpattern(dash)) xtitle(估计系数) ytitle(频数) title(安慰剂检验随机处理系数分布) subtitle(500次随机抽样) graphregion(color(white)) plotregion(color(white)) legend(off) note(垂直红线为真实政策效应)graph export 安慰剂检验.png, as(png) replace width(1200) height(800)如果真实系数红线落在随机分布的尾部说明真实政策效应显著区别于随机结果安慰剂检验通过。八、稳健性检验​​​​​​​* 1. 剔除特殊城市例如直辖市preservedrop if inlist(city, 北京,上海,天津)reghdfe congestion did $controls, absorb(city year) cluster(city)est store no_specialrestore * 2. 滞后一期被解释变量检验是否存在反向因果 reghdfe L.congestion did $controls, absorb(city year) cluster(city) est store lag* 3. 替换被解释变量用平均车速代替拥堵指数reghdfe speed did $controls, absorb(city year) cluster(city)est store alt_y* 把三种稳健性结果导出到一张表esttab no_special lag alt_y using 稳健性检验.rtf, replace b(%6.3f) se(%6.3f) star(* 0.1 ** 0.05 *** 0.01) title(稳健性检验) mtitles(剔除特殊城市 滞后一期 替换Y)结论保持稳健说明结果不依赖特定样本或特定因变量定义。九、异质性分析​​​​​​​* 按城市规模分组示例gen big_city inlist(city, 杭州,成都,武汉,南京,西安,长沙,苏州)* 大城市回归reghdfe congestion did $controls if big_city 1, absorb(city year) cluster(city)est store big* 中小城市回归reghdfe congestion did $controls if big_city 0, absorb(city year) cluster(city)est store small* 导出异质性结果esttab big small using 异质性_城市规模.rtf, replace b(%6.3f) se(%6.3f) star(* 0.1 ** 0.05 *** 0.01) title(城市规模异质性分析) mtitles(大城市 中小城市)通常大城市路网更复杂、出行需求更高政策效果可能更明显。十、写论文时的标准表述模板1. 基准结果共享单车试点显著降低了城市交通拥堵指数系数为××在5%水平上显著。2. 平行趋势政策实施前各期系数均不显著平行趋势假设成立。3. 安慰剂500次随机模拟中真实效应位于分布尾部经验p值小于0.05结果稳健。4. 稳健性剔除特殊城市、滞后被解释变量、替换因变量后核心结论保持不变。5. 异质性对大城市的缓解作用更强。新手避坑小贴士一定要先完成平行趋势检验再解读基准结果。reghdfe比普通xtreg更适合多维固定效应和聚类标准误。安慰剂检验的随机抽取数量要与真实处理组数量匹配。控制变量优先选择有理论或文献支撑的变量不要盲目堆砌。代码中所有变量名、城市名请替换成你自己的实际数据。把以上代码按顺序复制到Stata中运行就能得到一套完整、规范的DID实证结果。如果说是新手且时间紧迫可利用这个模板参考我上一期视频教学结合AI高效快速完成毕业论文实证卡在“套模板”Stata AI 这样用报错率直接降下来如果你的数据是面板、处理时点更多或者想加入核密度安慰剂图随时联系我接付费实证指导哦~小菲stata全网同名~后期还会录制DID对应的视频教学感谢大家的支持~祝大家发文顺利
返回列表