R语言did包多期DID:剔除无处理前后观测的面板成员
多期DID分析的样本筛选方案(R实现)
场景说明
我的数据为某街区房产租金价值的(部分)时间序列数据,其中“处理”指街区内出现银行网点关停事件,研究目标为估计该类关停事件对房产租金的影响,分析采用Callaway和Sant’Anna(2021)提出的多期双重差分(difference in difference, DID)方法,基于R语言的did包实现。
此前我参考数据框填充的相关方法,构建了适配did包分析要求的数据框,以下代码构造了包含4个房产示例样本的数据框df5,我额外添加了标识字段obs区分真实观测与填充值(该字段为did包非必需字段):
library(tidyverse) year <- c(2014, 2020, 2021) price <- c(100, 110, 120) df0 <- data.frame(cbind(id=1, year, price)) year <- c(2014, 2019, 2021) price <- c(100, 110, 120) df1 <- data.frame(cbind(id=1, year, price)) year <- c(2019, 2020, 2021) price <- c(210, 220, 230) df2 <- data.frame(cbind(id=2, year, price)) year <-c (2014, 2015, 2019) price <-c (300, 310, 320) df3 <- data.frame(cbind(id=3, year, price)) id <- c(rep(0,8), rep(1,8), rep(2,8), rep(3,8)) year <- c(rep(seq(2014,2021), 4)) price <- c(100, NA, NA, NA, NA, NA, 110, 120, 100, NA, NA, NA, NA, 110, NA, 120, NA, NA, NA, NA, NA, 210, 220, 230, 300, 310, NA, NA, NA, 320, NA, NA) df4 <- data.frame(id, year, price, obs = !is.na(price)) df5 <- df4 %>% group_by( id ) %>% fill( price, .direction = "downup" ) df5$gyear <- c(rep(0,8), rep(2016,8), rep(2017,8), rep(2020,8))
筛选规则
当前需要对房产样本做筛选,仅保留符合要求的样本,不符合要求的样本予以剔除,保留规则如下:
- 属于从未接受处理的对照组
- 属于处理组,且同时满足两个条件:至少存在1条处理前的真实观测、至少存在1条处理时点及之后的真实观测
示例样本判定结果:
- id=0:从未接受处理(
gyear == 0),予以保留- id=1:处理时点为2016年(
gyear == 2016),同时存在处理前、处理时点及之后的观测,予以保留- id=2:处理时点为2017年(
gyear == 2017),无处理前观测,需剔除- id=3:处理时点为2020年(
gyear == 2020),无处理时点及之后的观测,需剔除
筛选实现代码
直接按样本id分组判断保留条件即可,代码如下:
df5_filtered <- df5 %>% group_by(id) %>% filter( # 对照组样本直接保留 gyear == 0 | # 处理组需同时存在至少1条处理前真实观测、至少1条处理当期及之后真实观测 (sum(obs & year < gyear) >= 1 & sum(obs & year >= gyear) >= 1) ) %>% ungroup()
运行上述代码后,输出结果仅保留id=0和id=1的样本,完全匹配预期判定规则,可直接传入did包做后续多期DID估计。
参考文献
- Callaway, B. and Sant’Anna, P.H., 2021. Difference-in-differences with multiple time periods. Journal of Econometrics, 225(2), pp.200-230.
内容的提问来源于stack exchange,提问作者Stephen Clark
相关产品推荐
相关产品推荐

