Stata:断点回归RDD简明教程

发布时间:2020-06-17 阅读 173

作者:张子楠 (浙江财经大学)
E-mail: StataChina@163.com

Stata连享会   主页 || 视频 || 推文

连享会 - Stata 暑期班

线上直播 9 天:2020.7.28-8.7
主讲嘉宾:连玉君 (中山大学) | 江艇 (中国人民大学)
课程主页https://gitee.com/arlionn/PX | 微信版
助教招聘: 15 名,免费听课,详见课程主页


目录


专辑: 连享会-断点回归 RDD

1. RDD基本原理

断点回归分析被认为是最接近随机实验的检验方法,能够缓解参数估计的内生性问题,近来在越来越多的研究中得到使用。现有资料已经对断点回归方法的基本原理和效应识别进行了较为广泛的介绍,但对阶数选择和稳健性检验等问题的仍相对较少涉及。本文将基于Stata软件来系统介绍断点回归方法的图形观测、效应识别和有效性和稳健性检验。限于篇幅,本文将内容限定于清晰断点回归方法(Sharp Regression Discontinuity Design ),且只考虑只有一个断点和一个分配变量的问题。

2. 图形观察

2.1 生成模拟数据

我们先生成一份模拟数据,并保存为 RDD_simu_data0 。生成的数据中, z1 和 z2 为控制变量。 y1 为结果变量(outcome variable)。x 为分配变量(assignment vaiable)。分配点(cutoff point)设定为 0.5 ,从而x大于0.5 的为实验组,小于0.5的为对照组。

此外,在RDD检验中,我们通常还会对分配变量进行去中心化处理,即用分配变量减去分配点值。如本文中,令 xc=x-0.5 。进而 xc 大于 0 的位实验组,反之为对照组。

本部分的相应代码如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
	clear all	global dir d:/RDDStata	capture mkdir $dir	cd $dir		set obs 4000	set seed 123		gen x = runiform()     //分配变量	gen xc = x-0.5  //分配变量去中心化
gen e = rnormal()/5 // noise gen z1 = rnormal()*0.5 //控制变量 gen z2=1+3*invnormal(uniform())+sin(x*5)/3+e //另一个控制变量 gen T=0 replace T=1 if x>0.5 //treatment gen g0 = 0 + 3*log(x+1) + sin(x*6)/3 gen g1 = T + 3*log(x+1) + sin(x*6)/3 gen y1 = g1 + 0.5*z1 +0.3*z2+ e // outcome vaiable,with cutoff effect gen y0 = g0 + 0.5*z1 +0.3*z2+ e // outcome variable, without cutoff effect
label var y1 "Outcome variable (y)" label var y0 "Outcome variable (y)" label var x "Assignment variable (x)" label var xc "Centered Assignment variable (x-c)" label var T "T=1 for x>0.5, T=0 otherwise" drop e g* save "RDD_simu_data0.dta", replace //保存一份数据以备后用

2.2 断点效应的图形观察

使用 RDD 方法检验时,首先要确定结果变量在分配点存在跳跃现象,也即存在断点效应。可以用散点图来观察。下图中给出了不存在断点效应和存在断点效应两种情况。如下图所示,右侧图的结果变量y在分配点0.5处一个相对较为明显的跳跃,说明可能存在断点效应。

本部分相应代码如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
use "RDD_simu_data0.dta", clear
twoway (scatter y0 xc, msymbol(+) msize(*0.4) mcolor(black*0.3)) , title("无断点")graph save y0, replacetwoway (scatter y1 xc, msymbol(+) msize(*0.4) mcolor(black*0.3)) , title("有断点")graph save y1, replace
graph combine y0.gph y1.gph, row(1)

但用散点图来观察存在两个问题:一是样本太多时不够直观,二是实际分析时中跳跃现象可能不那么清晰。为此,我们可以利用拟合方法,对分配点左右分别拟合,通过观察两侧拟合线的的差异来更容易推测跳跃现象是否发生 RDD分析里提供了rdplot命令处理这项工作。下图中分别列出了利用散点图、 rdplot 命令 + 线性拟合、 rdplot命令 + 二阶多项式拟合图和rdplot命令 + 三阶多项式拟合图的结果。

本部分相应代码如下。其中 rdplot 命令中, c() 选项表示断点位置,不设定则默认为 0 。 p() 选项表示拟合的阶数。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
use "RDD_simu_data0.dta", clear
twoway (scatter y1 xc, msymbol(+) msize(*0.4) mcolor(black*0.3)), title("散点图")graph save scatter.gph, replacerdplot y1 xc, c(0) p(1) graph_options(title(线性拟合)) // 线性拟合图graph save rd1, replacerdplot y1 xc, c(0) p(2) graph_options(title(二次型拟合))//二次型拟合图graph save rd2, replacegraph combine scatter.gph rd1.gph rd2.gph

3. 政策效应估计

3.1 局部线性回归

使用局部线性回归法,是假定在断点邻域中的处理效应为线性,通过在左右两侧邻域分别进行线性回归并比较两侧回归系数差异来进行识别。局部回归检验的一个重要环节在于断点邻域大小的选择,也即 RDD 分析里带宽选择 (bandwidth selection) 的权衡问题。这是因为带宽越大,则意味着有越多的样本被纳入检验中,参数估计更准确,但也意味着样本随机性要求越难满足,内生性问题可能更严重。

本文中断点xc的邻域为 ([xc-h1,xc+h2]) , h1 和 h2 分别为左右两侧带宽。h1和h2可以相等,也可以不等。在断点分析中,可进行局部线性断点回归的命令有 rd、rdrobust 和 rdcv 三个命令。这三个都会自动给出该命令下最优带宽。本部分相应代码如下。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
//由于rdc命令回归较为耗时,本文仅随机抽取模拟数据中10%的观察值来演示。use "RDD_simu_data0.dta", clearset matsize 2000set seed 135sample 10          //随机抽取10%的观察值rdplot y1 xc, c(0) //检测一下,看看数据特征是否发生明显变化
// 不同局部线性断点回归命令 rd y1 xc, c(0)rdrobust y1 xc, c(0) p(1) rdcv y1 xc, thr(0) deg(1)

比较三个命令的回归结果,可以发现回归系数分别为 0.982,0.978和0.978 ,不同命令的系数结果基本一致。对于最优带宽选择,三个命令下分别为 0.208,0.187和0.2 ,十分接近。

此外, rd 命令不仅给出了最优带宽,还同时给出了带宽取最优带宽50%和200%的回归结果。观察 rd 命令结果可发现,50%、100%和200%带宽下回归系数也较为接近,分别为 0.954,0.982和0.954 。可知模拟数据的清晰断点回归结果对带宽选择并不敏感,这也表明回归结果是稳健的。

3.2 局部多项式回归

线性假设可能会错误估计了断点左右的回归系数,我们可以采取非线性拟合的办法进行弥补,即使用局部多项式断点回归方法。上文介绍的 rd、rdrobust和rdcv 三个命令,同样可以用于局部多项式断点回归分析。本部分相应代码如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
use "RDD_simu_data0.dta", clear    
rdrobust y1 xc //自动选择阶数rdrobust y1 xc, p(2) //二阶拟合rdrobust y1 xc, p(3) //三阶拟合

对于局部多项式断点回归,关键问题之一在于阶数的选择。我们利用赤池信息准则 (Akaike Information Criterion,AIC) 和贝叶斯信息准则 (Bayesian Information Criterion,BIC) ,选择不同阶数回归中AIC或BIC信息准则小的值。本文采用连玉君 Stata 培训班介绍的方法,结合 rdcv 命令来选择阶数。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
*-------------myic------------------  program define myic  version 13    qui estat ic    mat a = r(S)    estadd scalar AIC = a[1,5]    estadd scalar BIC = a[1,6]  end*-------------myic------------------*-Note: 调用自定义程序myic的方法:* (1) 选中上述代码,* (2) 按快捷键 Ctrl+R, 将程序读入内存

use "RDD_simu_data0.dta", clear set matsize 2000 set seed 135 sample 10 //rdcv回归较为耗时,仅随机抽取10%的观察值来演示。 #d ; rdcv y1 xc, thr(0) deg(1); myic; est store m1; rdcv y1 xc, thr(0) deg(2); myic; est store m2; rdcv y1 xc, thr(0) deg(3); myic; est store m3;#d cr // #d 表示 #delimit
*-对比回归结果 local m "m1 m2 m3" esttab `m', mtitle(`m') b(%6.3f) t(%6.3f) /// s(N r2 r2_a AIC BIC) nogap compress

回归结果的 AIC 和 BIC 信息如下表格所示,我们会选择 m2 ,即认为二次型拟合是最优的。

线性 二次型 三次型
AIC 761.160 446.327 819.628
BIC 775.494 464.740 849.097

3.3 全局多项式回归

全局多项式回归是使用了样本里所有数据来进行多项式回归。这在方法上,等价于局部回归分析里将左右带宽设置为分配变量的最小值和最大值。从而可以同样用上述命令来分析。需要注意的是,由于使用了全部样本,全局断点回归分析可能存在较为严重的内生性问题。本部分相应代码如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
			   use "RDD_simu_data0.dta", clear    sum xc local hvalueR=r(max)   local hvalueL= abs(r(min)) rdrobust y1 xc,   h(`hvalueL'  `hvalueR') //自动选择阶数rdrobust y1 xc,   h(`hvalueL'  `hvalueR') p(2) //二阶拟合rdrobust y1 xc,   h(`hvalueL'  `hvalueR') p(3) //三阶拟合

4. RDD有效性检验

4.1 局部平滑性的检验

对于局部平滑假设,是指除了结果变量,所有所有其它变量在断点附近都不应该存在处理效应,也即没有出现跳跃现象。在检验方法上,我们可以利用图形直接观察,也可以将每一个协变量作为安慰剂结果变量 (placebo outcomes) ,使用断点回归方法进行检验。

本部分图形检验和回归检验的代码如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
use "RDD_simu_data0.dta", clear		rdplot y1 xc  graph_options(title(z1平滑性检验)) 	graph save rdz1_smooth,  replacerdplot z2 xc  graph_options(title(z2平滑性检验))/               graph save rdz2_smooth,  replace
graph combine rdz1_smooth.gph rdz2_smooth.gph, title("变量z1 & z2的平滑性检验")
// 从图形,似乎是存在跳跃的,但这并不严格,要看回归结果 rdrobust z1 xcrdrobust z2 xc

两个回归结果的p值分别 0.399 和 0.741 ,说明不能拒绝不存在断点的假设,可知局部平滑假设满足。

4.2 驱动变量不受人为控制的检验

检验的思路在于,如果不存在人为操控,那么在断点附近样本的数量应该相近,才符合随机性。我们可以用 rddensity 命令来检验断点两侧样本数量是否相近。本部分相应代码如下所示,回归结的 p 值为 0.195 ,不能拒绝断点附近两测样本量大致相等的假设,可知驱动变量不受人为控制的假设满足。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
use "RDD_simu_data0.dta", clear		rdrobust y1 xclocal h = e(h_l)   //获取最优带宽rddensity xc, p(1) hl(`h') hr(`h')   

5. 稳健性检验

5.1 断点的安慰剂检验

稳健性检验的一个自然而然的思路在于选择一个不同于断点的值作为安慰剂断点 (placcebo cutoff points) 。如果断点回归结果变得不显著,则表明断点的真实性。相应代码分别取真实断点两侧 20%、40%、60% 和 80% 样本分位数处作为断点。作为对比,我们也放入了真实断点在图形里。如下图所示,五 个placebo cutoffs 的回归系数都不显著异于0,从而在这些点处不存在处理效应。

本部分相应代码如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line

use "RDD_simu_data0.dta", clear sum xc local xcmax=r(max) local xcmin= r(min)
forvalues i=1(1)4{local jr=`xcmax'/(`i'+1)local jl=`xcmin'/(`i'+1)rdrobust y1 xc if xc>0,c(`jr')estimates store jl`i'rdrobust y1 xc if xc<0,c(`jl') estimates store jr`i'}
//加上真实断点的回归结果,作为benchmark结果rdrobust y1 xc ,c(0) estimates store jbaseline
//输出图形local vlist "jl1 jl2 jl3 jl4 jbaseline jr4 jr3 jr2 jr1 "coefplot `vlist' , yline(0) drop(_cons) vertical

5.2 样本选择的敏感性检验

由于越接近断点的样本,越有动机去人为操控,我们删除最接近断点的样本,来观察回归是否显著(甜甜圈效应, donut hole approach )。如果仍旧存在,说明即使存在人为操控,断点效应仍旧存在。下面代码里,我们分别删除了断点附近 5%,10%,15%,25% 和 30% 的样本,进行了 6 组稳健性检验。图形给出了回归系数和 95% 的置信区间。可知,在删除 20% 及以下时,回归结果都保持显著。

本部分相应代码如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line

use "RDD_simu_data0.dta", clearsum xclocal xcmax=r(max)
forvalues i=1(1)6{local j=`xcmax'*0.05*`i'rdrobust y1 xc if abs(xc)>`j'estimates store obrob`i'}
//输出图形local vlist "obrob1 obrob2 obrob3 obrob4 obrob5 obrob6 "coefplot `vlist' , yline(0) drop(_cons) vertical

5.3 带宽选择的敏感性检验

带宽长度会显著影响回归结果,一个稳健的结果要求对带宽长度不那么敏感。下面代码里,我们先通过rdrobust命令提取最优带宽h,然后分别手动设置带宽为 h 的 25%-400% 倍,看回归结果是否仍旧显著。图形给出了回归系数和95%的置信区间。可知,在最优带宽 25%-400% 范围内,回归结果保持显著,说明结论较为可靠。

本部分相应代码如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
use "RDD_simu_data0.dta", clearrdrobust y1 xc     //自动选择最优带宽  local h = e(h_l)   //获取最优带宽
forvalues i=1(1)8{local hrobust=`h'*0.25*`i'rdrobust y1 xc ,h(`hrobust')estimates store hrob`i'}
//输出图形local vlist "hrob1 hrob2 hrob3 hrob4 hrob5 hrob6 hrob7 hrob8 "coefplot `vlist' , yline(0) drop(_cons) vertical

连享会 - 文本分析与爬虫 - 专题视频

主讲嘉宾:司继春 || 游万海

连享会-文本分析与爬虫-专题视频教程

连享会 - 效率分析专题

已上线:可随时购买学习+全套课件,课程主页 已经放置板书和 FAQs
主讲嘉宾:连玉君 | 鲁晓东 | 张宁
课程主页微信版https://gitee.com/arlionn/TE

连享会-效率分析专题视频
连享会-效率分析专题视频

相关课程

连享会-直播课 上线了!
http://lianxh.duanshu.com

免费公开课:


课程一览

支持回看,所有课程可以随时购买观看。

专题 嘉宾 直播/回看视频
Stata暑期班 连玉君
江艇
线上直播 9 天
2020.7.28-8.7
效率分析-专题 连玉君
鲁晓东
张 宁
视频-TFP-SFA-DEA
已上线,3天
文本分析/爬虫 游万海
司继春
视频-文本分析与爬虫
已上线,4天
空间计量系列 范巧 空间全局模型, 空间权重矩阵
空间动态面板, 空间DID
研究设计 连玉君 我的特斯拉-实证研究设计-幻灯片-
面板模型 连玉君 动态面板模型-幻灯片-
直击面板数据模型 [免费公开课,2小时]

Note: 部分课程的资料,PPT 等可以前往 连享会-直播课 主页查看,下载。


关于我们

  • Stata连享会 由中山大学连玉君老师团队创办,定期分享实证分析经验。直播间 有很多视频课程,可以随时观看。
  • 连享会-主页知乎专栏,300+ 推文,实证分析不再抓狂。
  • 公众号推文分类: 计量专题 | 分类推文 | 资源工具。推文分成 内生性 | 空间计量 | 时序面板 | 结果输出 | 交乘调节 五类,主流方法介绍一目了然:DID, RDD, IV, GMM, FE, Probit 等。
  • 公众号关键词搜索/回复 功能已经上线。大家可以在公众号左下角点击键盘图标,输入简要关键词,以便快速呈现历史推文,获取工具软件和数据下载。常见关键词:
    • 课程, 直播, 视频, 客服, 模型设定, 研究设计, 暑期班
    • stata, plus,Profile, 手册, SJ, 外部命令, profile, mata, 绘图, 编程, 数据, 可视化
    • DID,RDD, PSM,IV,DID, DDD, 合成控制法,内生性, 事件研究, 交乘, 平方项, 缺失值, 离群值, 缩尾, R2, 乱码, 结果
    • Probit, Logit, tobit, MLE, GMM, DEA, Bootstrap, bs, MC, TFP, 面板, 直击面板数据, 动态面板, VAR, 生存分析, 分位数
    • 空间, 空间计量, 连老师, 直播, 爬虫, 文本, 正则, python
    • Markdown, Markdown幻灯片, marp, 工具, 软件, Sai2, gInk, Annotator, 手写批注, 盈余管理, 特斯拉, 甲壳虫, 论文重现, 易懂教程, 码云, 教程, 知乎

连享会主页  lianxh.cn
连享会主页 lianxh.cn

连享会小程序:扫一扫,看推文,看视频……


扫码加入连享会微信群,提问交流更方便

✏ 连享会学习群-常见问题解答汇总:
https://gitee.com/arlionn/WD