创建first.treat变量用于多期diff-in-diff时遇无从未处理组错误求助
问题描述
我有1997-2019年PSF覆盖数据,结构如下:
ano id_mun tratado 1998 313240 0 1998 313250 0 1998 313260 1 . . . . . . . . . 2019 317220 1
其中tratado=1表示市镇接受项目(处理组),0为未接受。我需要识别每个市镇首次被处理的年份,创建first.treat变量用于多期双重差分(DID)估计,使用了以下代码:
df1 = amostra_final%>% group_by(id_mun) %>% mutate(first.treat = min( if_else(tratado == 1, ano, NA_integer_), na.rm = TRUE )) %>% ungroup()
运行后出现错误:
Error in pre_process_did(yname = yname, tname = tname, idname = idname, : There is no available never-treated group
问题原因
这个错误来自多期DID工具(比如did包)的前置检查:这类模型要求必须存在从未接受处理的对照组(即所有年份tratado都为0的市镇),但当前数据中所有市镇最终都被纳入了项目,没有始终未处理的样本;或者是first.treat变量的标记逻辑有误,导致工具无法识别已存在的从未处理组。
解决方案
1. 先确认是否真的没有从未处理的市镇
先运行代码排查数据状态:
# 统计每个市镇是否曾经被处理 mun_treat_status <- amostra_final %>% group_by(id_mun) %>% summarize(ever_treated = max(tratado)) # 查看从未处理的市镇数量 nrow(filter(mun_treat_status, ever_treated == 0))
如果结果为0,说明确实没有从未处理组,需要调整分析策略;如果结果大于0,说明是first.treat变量的标记有问题,直接看方案3。
2. 无从未处理组时的分析调整
方式一:采用相对时间模型
放弃依赖从未处理组,转而估计处理的动态效应,以每个市镇首次处理前的时期为基准:
# 创建相对时间变量 df1 <- amostra_final %>% group_by(id_mun) %>% mutate( first.treat = min(if_else(tratado == 1, ano, NA_integer_), na.rm = TRUE), # rel_time为负表示处理前,0为处理当年,正为处理后;从未处理的设为NA rel_time = ano - first.treat ) %>% ungroup() # 用双向固定效应模型估计 library(lfe) dynamic_model <- felm(y ~ rel_time | id_mun + ano, data = df1) summary(dynamic_model)
方式二:使用合成控制法
如果处理组市镇数量较少,可为每个处理组构建“合成对照组”(由未处理时期的其他市镇加权组成),替代传统DID的从未处理组,适合用Synth或gsynth包实现。
3. 修正first.treat变量(存在从未处理组时)
如果实际有从未处理的市镇,但当前代码给它们的first.treat赋值为Inf(因为min(NA, na.rm=TRUE)返回无穷大),导致DID工具无法识别,需要手动标记从未处理组的first.treat为NA或超出样本范围的年份:
df1 <- amostra_final %>% group_by(id_mun) %>% mutate( first.treat = case_when( max(tratado) == 0 ~ NA_integer_, # 从未处理的设为NA TRUE ~ min(if_else(tratado == 1, ano, NA_integer_), na.rm = TRUE) ) ) %>% ungroup()
这样DID工具就能正确识别从未处理组作为对照组了。
内容的提问来源于stack exchange,提问作者Alex Gois
相关产品推荐
相关产品推荐

