目录
Diff-in-Diff with Fixed Effects
Diff-in-Diff with OLS
尽管您可以通过手工计算平均值或取差值来实现 DID,但如果不包含相当数量的线性回归,这就不是一个值得尊敬的因果推理章节。毫不奇怪,你可以用饱和回归模型得到完全相同的 DID 估计值。首先,让我们按城市和时期(干预后和干预前)对每日数据进行分组。然后,对于每个城市和时期的组合,您可以得到平均每日下载次数。我还会得到每个时期的开始日期和每个城市的干预状态。开始日期并不用于估算,但它有助于了解干预发生的时间:
did_data = (mkt_data
.groupby(["city", "post"])
.agg({"downloads":"mean", "date": "min", "treated": "max"})
.reset_index())
did_data.head()
使用此城市按周期数据集,您可以估计以下线性模型:
参数估计值 β3 将是 DID 估计值。要知道为什么会这样,请注意 β0 是控制的基线。在这种情况下,β0 是 2021-05-15 之前控制城市的下载量水平。如果打开受治疗城市虚拟值,则得到 β0 + β1。因此,β0 + β1 是受治疗城市的基线,也是干预前的基线。β1 只是治疗城市与对照城市之间的基线差异。如果关闭干预假值,打开干预后假值,则得到 β0 + β2,即干预后对照城市的水平。β2 是对照组的趋势。这是对照组从干预前到干预后的增长幅度。
概括地说,β1 是指从对照组到干预组的增量,β2 是指从干预前到干预后的增量。最后,如果同时打开治疗前和治疗后的虚拟变量,则得到 β0+ β1+ β2+ β3。这是干预后受治疗城市的水平,也就是说,β3 是指从受治疗城市到对照城市、从干预前到干预后时期所得到的结果增量。换句话说,这就是差分估计法:
import statsmodels.formula.api as smf
smf.ols(
'downloads ~ treated*post', data=did_data
).fit().params["treated:post"]
0.691735953640
Diff-in-Diff with Fixed Effects
另一种理解 DID 的方法是时间和单位固定效应模型(双向固定效应或 TWFE)。在该模型中,有干预效应 τ、单位和时间固定效应 αi 和 γt:
为了整理,我在这里使用。
如果您对该模型进行估计,与 W 相关的参数估计值将与您之前得到的 DID 估计值相匹配,并恢复 ATT。为此您可以通过使用虚拟变量或去数据含义来估计固定效应。这里,为了简单起见,我们只使用虚拟变量的方法。也就是说,我们用 C(city)和 C(post)来包含城市和时期虚拟变量。此外,您还需要将处理过的虚拟数据和职位虚拟数据相乘来创建 W。请记住,"*"运算符可以创建两个项之间的交互作用和项本身的交互作用。由于您只需要交互作用,因此需要使用 : 运算符:
m = smf.ols('downloads ~ treated:post + C(city) + C(post)',
data=did_data).fit()
m.params["treated:post"]
0.691735953640
再一次,你得到了完全相同的参数估计。
Multiple Time Periods
典型的 DID 设置要求只有四个数据单元格:干预前、干预后、治疗组和对照组。但它并不要求将干预前和干预后的时间段合并为一个区组。典型的 DID 只要求有所谓的区块设计:一组从未接受治疗的单元和一组最终在同一时间段接受治疗的单元。也就是说,你不能让干预在不同时刻向单位推出(你很快就会了解到)。您正在使用的营销示例正是这种格式,这意味着您不必按照干预前和干预后的时间段进行汇总。您只需按原样使用即可。
您可以在下图中直观地看到这种分块设计,该图绘制了每个城市随时间变化的干预分配情况。图中还显示了结果在不同时间段的变化情况,这样你就能更好地理解 DID 所关注的问题。也就是说,DID 试图观察干预措施实施后,治疗组和对照组之间的差异是否会扩大:
要利用这些分类数据得出 DID 估计值,可以使用与之前完全相同的公式。也就是说,您既可以将结果与处理后虚拟变量和处理后虚拟变量之间的交互作用进行回归,也可以将结果与处理后虚拟变量和处理后虚拟变量之间的交互作用进行回归:
m = smf.ols('downloads ~ treated*post', data=mkt_data).fit()
m.params["treated:post"]
0.6917359536407226
或者您可以使用固定效果规范:
m = smf.ols('downloads ~ treated:post + C(city) + C(date)',
data=mkt_data).fit()
m.params["treated:post"]
0.691735953640
我刚刚展示了一系列获得完全相同的 DID 估计值的方法。我希望通过这样做,你能从所有方法中获得启发,从而增加你理解发生了什么的机会。但是,如果你仔细观察,我故意隐藏了你刚才运行的回归的置信区间。这是因为这些回归的置信区间可能是错误的。