双向固定效应(TWFE)模型
目录
- 经典的2x2 DiD或双向固定效应模型(TWFE)
- 三重差分估计量(DDD)
- 通用TWFE函数形式
- Stata代码
- 添加更多时间段
- 更多单位,相同处理时间,不同处理效应
- 更多单位,差异处理时间,不同处理效应
经典的2x2 DiD或双向固定效应模型(TWFE)
未完成
让我们从经典的双向固定效应(TWFE)模型开始:
\[y_{it} = \beta_0 + \beta_1 Treat_i + \beta_2 Post_t + \beta_3 Treat_i Post_t + \epsilon_{it}\]上述2x2模型可以用以下表格来解释:
处理组 = 0 | 处理组 = 1 | 差异 | |
---|---|---|---|
后处理 = 0 | \(\beta_0\) | \(\beta_0 + \beta_1\) | \(\beta_1\) |
后处理 = 1 | \(\beta_0 + \beta_2\) | \(\beta_0 + \beta_1 + \beta_2 + \beta_3\) | \(\beta_1 + \beta_3\) |
差异 | \(\beta_2\) | \(\beta_2 + \beta_3\) | \(\beta_3\) |
三重差分估计量(DDD)
未完成
三重差分估计量本质上采用两个DD,一个针对目标分析单位,包含处理组和未处理组。这与另一个在前后处理期间类似的组进行比较。因此实际上有两个处理。一个是对期望组的实际处理进行测试,另一个是对安慰剂比较组应用相同的干预。
\[y_{it} = \beta_0 + \beta_1 P_{i} + \beta_2 C_{j} + \beta_3 T_t + \beta_4 (P_i T_t) + \beta_5 (C_j T_t) + \beta_6 (P_i C_j) + \beta_7 (P_i C_j T_t) + \epsilon_{it}\]其中我们有3x3组合:P = {0,1}, T={0,1}, C={0,1}。与2x2 DD的情况一样,这里感兴趣的系数是 \(\beta_7\)。这也可以用表格形式分解。但与其创建一个大表格,结果通常表示为C = 0,或主要处理组,以及C = 1,或主要比较组。两者之间的差异归结为 \(\beta_7\)。让我们在这里看到:
主要组(\(C = 0\)):
T = 0 | T = 1 | 差异 | |
---|---|---|---|
P = 0 | \(\beta_0\) | \(\beta_0 + \beta_3\) | \(\beta_3\) |
P = 1 | \(\beta_0 + \beta_1\) | \(\beta_0 + \beta_1 + \beta_3 + \beta_4\) | \(\beta_3 + \beta_4\) |
差异 | \(\beta_1\) | \(\beta_1 + \beta_4\) | \(\beta_4\) |
比较组(\(C = 1\)):
T = 0 | T = 1 | 差异 | |
---|---|---|---|
P = 0 | \(\beta_0 + \beta_2\) | \(\beta_0 + \beta_2 + \beta_3 + \beta_5\) | \(\beta_3 + \beta_5\) |
P = 1 | \(\beta_0 + \beta_1 + \beta_2 + \beta_6\) | \(\beta_0 + \beta_1 + \beta_2 + \beta_3 + \beta_4 + \beta_5 + \beta_6 + \beta_7\) | \(\beta_3 + \beta_4 + \beta_5 + \beta_7\) |
差异 | \(\beta_1 + \beta_6\) | \(\beta_1 + \beta_4 + \beta_6 + \beta_7\) | \(\beta_4 + \beta_7\) |
让我们取两个矩阵的差异或(C = 1) - (C = 0):
T = 0 | T = 1 | 差异 | |
---|---|---|---|
P = 0 | \(\beta_2\) | \(\beta_2 + \beta_5\) | \(\beta_5\) |
P = 1 | \(\beta_2 + \beta_6\) | \(\beta_2 + \beta_5 + \beta_6 + \beta_7\) | \(\beta_5 + \beta_7\) |
差异 | \(\beta_6\) | \(\beta_6 + \beta_7\) | \(\beta_7\) |
最终得到主要差异 \(\beta_7\)。注意,这种表格逻辑也比为每个组合定义一长串期望要简单得多。
通用TWFE函数形式
未完成
如果我们有多个时间段和处理单位,经典的2x2 DiD可以扩展到以下通用函数形式:
\[y_{it} = \alpha_{i} + \alpha_t + \beta^{TWFE} D_{it} + \epsilon_{it}\]Stata代码
让我们在Stata中生成一个简单的2x2示例。第一步定义面板结构。由于是2x2,我们只需要两个单位和两个时间段:
clear
local units = 2
local start = 1
local end = 2
local time = `end' - `start' + 1
local obsv = `units' * `time'
set obs `obsv'
egen id = seq(), b(`time')
egen t = seq(), f(`start') t(`end')
sort id t
xtset id t
lab var id "面板变量"
lab var t "时间变量"
接下来我们定义处理组和一个不添加任何变化或误差项的通用TWFE模型:
gen D = id==2 & t==2
gen btrue = cond(D==1, 2, 0)
gen Y = id + 3*t + btrue*D
根据最后一行,处理效应应该对后处理组的Y产生3个单位的影响。我们可以通过绘制数据来检查这一点:
lab de prepost 1 "前" 2 "后"
lab val t prepost
twoway ///
(connected Y t if id==1) ///
(connected Y t if id==2) ///
, ///
legend(order(1 "id=1" 2 "id=2")) ///
xlabel(1 2, valuelabel) ylabel(4(1)10)
这给了我们:
我们可以看到,在后处理期间,蓝线和橙线之间的差异是3,在前处理期间是1,净增长为2个单位。这也等于我们指定的处理量。
我们也可以通过简单的面板回归来恢复这一点:
xtset id t
xtreg Y D t, fe
在回归中,你会看到D的系数,\(\beta^{TWFE}\) = 2,如预期的那样。另一种方法是使用reghdfe
包,我们稍后也会在其他示例中调用:
reghdfe Y D, absorb(id t)
这再次给了我们D系数的相同结果。
添加更多时间段
现在我们熟悉了2x2示例,让我们添加更多时间段。每个单位10个怎么样:
clear
local units = 2
local start = 1
local end = 10
local time = `end' - `start' + 1
local obsv = `units' * `time'
set obs `obsv'
egen id = seq(), b(`time')
egen t = seq(), f(`start') t(`end')
sort id t
xtset id t
lab var id "面板变量"
lab var t "时间变量"
我们只是做一个简单的处理,其中id=2在第5个时间段增加3个单位并保持在那里:
gen D = id==2 & t>=5
lab var D "已处理"
gen btrue = cond(D==1, 3, 0)
gen Y = id + t + btrue*D
lab var Y "结果变量"
我们也可以将其可视化如下:
我们也可以运行Stata代码:
xtreg Y D t, fe
reghdfe Y D, absorb(id t)
xtreg
选项显示\(t\)平均增加1个单位,这是我们期望的。截距等于1.5,这是如果蓝线和橙线外推到\(t = 0\)点的平均值。而\(\beta^{TWFE}\) = 3,干预效应的真实值。
更多单位,相同处理时间,不同处理效应
让我们从一个非常简单的案例开始,我们有一个对照组,两个处理组。两个T组在同一时间接受处理,但处理强度不同:
clear
local units = 3
local start = 1
local end = 10
local time = `end' - `start' + 1
local obsv = `units' * `time'
set obs `obsv'
egen id = seq(), b(`time')
egen t = seq(), f(`start') t(`end')
lab var id "面板变量"
lab var t "时间变量"
sort id t
xtset id t
gen D = 0
replace D = 1 if id>=2 & t>=5
lab var D "已处理"
cap drop Y
gen Y = 0
replace Y = cond(D==1, 2, 0) if id==2
replace Y = cond(D==1, 4, 0) if id==3
lab var Y "结果变量"
并绘制它:
twoway ///
(connected Y t if id==1) ///
(connected Y t if id==2) ///
(connected Y t if id==3) ///
, ///
xline(4.5) ///
xlabel(1(1)10) ///
legend(order(1 "id=1" 2 "id=2" 3 "id=3"))
从中我们得到:
这里我们可以看到后处理对id=2的平均效应为2,对id=3为4。这意味着ATT等于\(\beta^{TWFE}\)=3,我们也可以通过恢复系数来检查:
xtreg Y D t, fe
虽然在这里检查平均处理效应很容易,因为它们没有时间或面板固定效应,我们基本上可以直观地看到结果是如何变化的。但如果我们添加控制变量,它会变得有点复杂。让我们一次性生成代码:
clear
local units = 3
local start = 1
local end = 10
local time = `end' - `start' + 1
local obsv = `units' * `time'
set obs `obsv'
egen id = seq(), b(`time')
egen t = seq(), f(`start') t(`end')
sort id t
xtset id t
lab var id "面板变量"
lab var t "时间变量"
gen D = 0
replace D = 1 if id>=2 & t>=5
lab var D "已处理"
cap drop Y
gen Y = 0
replace Y = id + t + cond(D==1, 0, 0) if id==1
replace Y = id + t + cond(D==1, 2, 0) if id==2
replace Y = id + t + cond(D==1, 4, 0) if id==3
lab var Y "结果变量"
twoway ///
(connected Y t if id==1) ///
(connected Y t if id==2) ///
(connected Y t if id==3) ///
, ///
xline(4.5) ///
xlabel(1(1)10) ///
legend(order(1 "id=1" 2 "id=2" 3 "id=3"))
从之前的示例中,我们知道ATT等于\(\beta^{TWFE}\)=3,但从图表中我们不能这么清楚地看到这一点。这是因为我们需要去除面板和id时间趋势。虽然我们也可以手动进行部分剔除(但我们不会),我们可以使用我们的回归规范:
xtreg Y D t, fe
这给出了ATT=3,这是两个处理变量的平均值。
在这里,我想补充一点,平行趋势假设在上述回归规范中得到了控制。如果没有考虑到这些,那么我们基本上会得到错误的ATT。我们可以在以下回归中看到D系数:
reg Y D // 不控制任何效应
reg Y D i.t // 仅时间固定效应
reg Y D i.id // 仅面板固定效应
reg Y D i.t i.id // 面板和时间固定效应(正确!)
更多单位,差异处理时间,不同处理效应
现在让我们进入最后一部分:具有差异时间的处理。这里我们再次生成一个虚拟数据集,但现在去除面板和时间固定效应。正如我们在上面看到的,回归隔离了面板固定效应,我们恢复了感兴趣的系数\(\beta^{TWFE}\)。
clear
local units = 3
local start = 1
local end = 10
local time = `end' - `start' + 1
local obsv = `units' * `time'
set obs `obsv'
egen id = seq(), b(`time')
egen t = seq(), f(`start') t(`end')
sort id t
xtset id t
lab var id "面板变量"
lab var t "时间变量"
gen D = 0
replace D = 1 if id==2 & t>=5
replace D = 1 if id==3 & t>=8
lab var D "已处理"
gen Y = 0
replace Y = D * 2 if id==2 & t>=5
replace Y = D * 4 if id==3 & t>=8
lab var Y "结果变量"
twoway ///
(connected Y t if id==1) ///
(connected Y t if id==2) ///
(connected Y t if id==3) ///
, ///
xline(4.5 7.5) ///
xlabel(1(1)10) ///
legend(order(1 "id=1" 2 "id=2" 3 "id=3"))
这给了我们这个图:
该图显示,组id=2在t=5时获得干预并保持处理状态,而组id=3在t=8时获得干预并保持处理状态。那么这里的ATT是什么?
与之前的示例不同,我们可以通过查看图表来推导ATT,这里并不那么简单。即使没有时间和面板固定效应,处理时间的差异确实使面板和时间的变化变得相关。不深入数学,为了恢复实际的ATT,我们需要对处理和非处理观测值的时间和面板效应进行平均。
我们可以做这些回归来查看结果:
reg Y D // 不控制任何效应
reg Y D i.t // 仅时间固定效应
reg Y D i.id // 仅面板固定效应
reg Y D i.t i.id // 面板和时间固定效应(正确!)
最后一个回归给了我们正确的ATT,即\(\beta^{TWFE}\) = 2.91。这实际上是在对面板和时间变量进行平均后,\(y_{it}\)的平均增长。
我们也可以使用标准命令来恢复这一点:
xtreg Y D i.t, fe
reghdfe Y D, absorb(id t)
这给了我们相同的答案\(\beta^{TWFE}\) = 2.91。
让我们思考一下这个数字。我们有两个在不同时间发生的处理,具有不同的处理效应。因此前后处理的定义不再清楚。未处理与已处理也不清楚。如果我们看区间\(5\leq t < 8\),只有id=2在变化,其他两个变量是常数。但在最后一个区间,其中\(t \geq 8\),那么只有id=3显示变化,而其他两个面板变量在这个区间是常数(即使id=2在这里被处理)。
正是这些组合在Bacon分解部分中被解开,这就是为什么仔细理解分解很重要。