You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

双重差分(DID)回归分析中虚拟变量异常问题技术求助

DID回归模型交互项奇异值问题排查与解决

我看到你在用双重差分法(DID)分析学生评估数据时,手动计算DID结果正常,但回归模型里的交互项却因奇异值无法估计——这大概率是虚拟变量构造逻辑重复导致的完全多重共线性,咱们一步步来解决:

问题根源拆解

你构造的post_treatment_treated变量,本质上就是treatmentpost_treatment的交互项本身:

assessment$post_treatment_treated <- ifelse(assessment$treatment==1 & assessment$ï..year>=2017,1,0)

当你在回归里同时放入post_treatment_treatedpost_treatment,再加上它们的交互项时,三个变量之间存在完全线性依赖关系,R会判定交互项为奇异值,直接跳过估计。

正确的DID回归设置

DID的核心是处理组标识时间标识,以及两者的交互项(即真正的DID效应),下面是标准实现步骤:

1. 规范变量构造

不需要手动构造交互项,lm()函数可以通过*自动生成主效应和交互项,避免重复:

# 确保treatment是分类变量(可选,但输出结果更直观)
assessment$treatment <- as.factor(assessment$treatment)
# 定义时间虚拟变量:2017及以后为处理后时期
assessment$post_treatment <- ifelse(assessment$ï..year >= 2017, 1, 0)

2. 标准DID回归的两种写法(效果完全一致)

写法一:用*自动生成交互项(推荐)

# 语言科目DID回归
did_lang <- lm(lang_percentage ~ treatment * post_treatment, data = assessment)
summary(did_lang)

# 数学科目DID回归
did_math <- lm(maths_percentage ~ treatment * post_treatment, data = assessment)
summary(did_math)

写法二:手动指定主效应和交互项

# 先构造交互项
assessment$did_term <- assessment$treatment * assessment$post_treatment
# 回归模型
did_lang <- lm(lang_percentage ~ treatment + post_treatment + did_term, data = assessment)
summary(did_lang)

运行后,交互项(treatment1:post_treatment)的系数就对应你手动计算的DID值,完美匹配。

修正手动计算的时间范围问题

你之前手动计算平行趋势时,时间范围存在重叠(>=2016<=2017包含了2017年),这会导致计算结果偏差,修正后的代码如下:

# 语言科目正确手动计算DID
control_lan_pretreatment <- mean(assessment$lang_percentage[assessment$treatment==0 & assessment$ï..year < 2017])
control_lan_posttreatment <- mean(assessment$lang_percentage[assessment$treatment==0 & assessment$ï..year >= 2017])
treated_lan_pretreatment <- mean(assessment$lang_percentage[assessment$treatment==1 & assessment$ï..year < 2017])
treated_lan_posttreatment <- mean(assessment$lang_percentage[assessment$treatment==1 & assessment$ï..year >= 2017])
# 标准DID公式:(处理组前后差) - (控制组前后差)
did_lan_manual <- (treated_lan_posttreatment - treated_lan_pretreatment) - (control_lan_posttreatment - control_lan_pretreatment)

修正后的手动计算值会和回归模型的交互项系数完全一致。

额外优化建议

  • 利用数据里的prepost变量:如果"bl"代表预处理时期,可以直接用它定义post_treatment,避免年份范围错误。
  • 加入控制变量:比如genderclass等,提升模型解释力,扩展模型示例:
    did_lang <- lm(lang_percentage ~ treatment * post_treatment + gender + class, data = assessment)
    
  • 面板数据优化:如果是同一学生/班级的多期数据,推荐用plm包做固定效应回归,控制个体和时间固定效应,更符合DID的平行趋势假设。

内容的提问来源于stack exchange,提问作者Rahul Shukla

火山引擎 最新活动