Having an unbalanced panel is not a problem nowadays. In the past, when econometrics had to be done by hand, inverting matrices for unbalanced panels was more difficult but for computers this is not a problem. The only worry connected today with this is the question why the panel is unbalanced: is it due to attrition? If yes, is this attrition random or related to characteristics of the statistical units? For instance, in surveys people with higher education tend to be more responsive and stay in the panel longer for that reason.
Regarding the fixed effects model, have you checked whether the variables that are time-invariant in theory are actual not varying over time? Sometimes coding errors sneak in and then all the sudden a variable varies over time when it shouldn't. One way of checking this is to use the xtsum
command which displays overall, between, and within summary statistics. The time-invariant variables should have a zero within standard deviation. If they don't then something went wrong in the coding.
Having a negative Hausman test statistics is a bad thing because the matrices that the test is built on are positive semi-definite and therefore the theoretical values of the test are positive. Negative values point towards model misspecification or a too small sample (related to this is this question).
If you cluster your standard errors you also need a modified version of the Hausman test. This is implemented in the xtoverid
command. You can use it like this:
xtreg ln_r_prisperkg_Frst_102202 Dflere_mottak_tur i.landingsfylkekode i.kvartiler_ny markedsk_torsk gjenv_TAC_NØtorsk_år_prct lalder_fartøy i.fangstr r_minst_Frst_torsk gjenv_kvote_NØtorsk_fartøy_prct i.lengde_gruppering mobilitet, fe vce(cluster fartyid)
xtoverid
Rejecting the null rejects the validity of the assumptions underlying the random effects mode.
The xtset
command only takes into account the unit id for fixed effects estimation. The time variable does not eliminate time fixed effects. So if you do
xtset id time
xtreg y x, fe
will give you the exact same results as
xtset id
xtreg y x, fe
The time variable is only specified for commands for which the sorting order of the data matters, for instance xtserial
which tests for panel autocorrelation requires this. This has been discussed here. So if you want to include time fixed effects, you need to include the day dummies separately via i.day
, for example. In this context, the season and year dummies make sense so it's good that you use them.
You need to compare apples to apples, so use clustering with OLS and clustering with xtreg, fe
(or robust with xtreg, fe
, which will default to clustering as Thomas pointed out). These coefficient equivalences are limited to two-period (one pre, and one post) datasets with treatment at the same time for all treated units.
Here's an example of 2x2 DID on a public dataset demonstrating this. Here NJ restaurants are treated (become subject to the minimum wage increase) and PA restaurant are not. February '92 (t=0) is pre and November '92 is post (t=1). The DID parameter is the interaction of t = 1 and NJ = 1. The outcome fte is full-time equivalent employees. Here I will balance the panel in order to get xtreg, fe
and OLS to give the same coefficient estimates. If the panel is unbalanced (consists of repeated cross-sections), xtreg, fe
will drop some observations that appear in only one year and the estimates will no longer match OLS or manual calculations. You may want to stick with clustered OLS if you have a repeated cross-section.
Here is the result. Note that you can use factor variable notation to create the interactions rather than hard coding them.
. use http://fmwww.bc.edu/repec/bocode/c/CardKrueger1994.dta, clear
(Dataset from Card&Krueger (1994))
. drop if id == 407 // duplicate restaurant
(4 observations deleted)
. drop if missing(fte, treated, t, id)
(19 observations deleted)
. bysort id: keep if _N==2 // balance the panel
(19 observations deleted)
. xtset id t
panel variable: id (strongly balanced)
time variable: t, 0 to 1
delta: 1 unit
.
. /* calculate DID by hand */
. table treated t, c(mean fte N fte) row col
----------------------------------------
New |
Jersey = |
1; |
Pennsylva | Feb. 1992 = 0; Nov. 1992 = 1
nia = 0 | 0 1 Total
----------+-----------------------------
PA | 20.17333 17.65 18.91167
| 75 75 150
|
NJ | 17.06927 17.51831 17.29379
| 314 314 628
|
Total | 17.66774 17.5437 17.60572
| 389 389 778
----------------------------------------
. di %9.3f (17.51831 - 17.06927) - (17.65 - 20.17333)
2.972
.
. /* fit models */
. eststo ols_robust: qui reg fte i.treated##i.t, robust
. eststo xtreg_robust: qui xtreg fte i.treated##i.t, fe robust
. eststo xtreg_clust: qui xtreg fte i.treated##i.t, fe cluster(id)
. eststo ols_clust: qui reg fte i.treated##i.t, cluster(id)
.
. capture ssc install estout
. esttab *, se(%9.7f) noomitted drop(0.treated 0.t 0.treated#0.t) modelwidt(15) mtitles label varwidth(35)
---------------------------------------------------------------------------------------------------------------
(1) (2) (3) (4)
ols_robust xtreg_robust xtreg_clust ols_clust
---------------------------------------------------------------------------------------------------------------
NJ -3.104* -3.104*
(1.4475664) (1.4484988)
Feb. 1992 = 0; Nov. 1992 = 1=1 -2.523 -2.523* -2.523* -2.523*
(1.6371048) (1.2498119) (1.2498119) (1.2506190)
NJ # Feb. 1992 = 0; Nov. 1992 = 1=1 2.972 2.972* 2.972* 2.972*
(1.7822146) (1.3337493) (1.3337493) (1.3346107)
Constant 20.17*** 17.67*** 17.67*** 20.17***
(1.3591695) (0.2232501) (0.2232501) (1.3600450)
---------------------------------------------------------------------------------------------------------------
Observations 778 778 778 778
---------------------------------------------------------------------------------------------------------------
Standard errors in parentheses
* p<0.05, ** p<0.01, *** p<0.001
Clustering in DID settings is a good idea for reasons outlined in Bertrand, Duflo, and Mullainathan's 2004 QJE paper. Clustering at the level of treatment is also a good idea, but here that is not feasible since there are not enough clusters (since treatment is a state law and we have data from two states only) for that to work well. Generally your SEs will go up when you cluster in DID, but if the errors are negatively correlated within cluster, they might shrink. See this post for the reasons why.
Code:
estimates clear
cls
use http://fmwww.bc.edu/repec/bocode/c/CardKrueger1994.dta, clear
drop if id == 407 // duplicate restaurant
drop if missing(fte, treated, t, id)
bysort id: keep if _N==2 // balance the panel
xtset id t
/* calculate DID by hand */
table treated t, c(mean fte N fte) row col
di %9.3f (17.51831 - 17.06927) - (17.65 - 20.17333)
/* fit models */
eststo ols_robust: qui reg fte i.treated##i.t, robust
eststo xtreg_robust: qui xtreg fte i.treated##i.t, fe robust
eststo xtreg_clust: qui xtreg fte i.treated##i.t, fe cluster(id)
eststo ols_clust: qui reg fte i.treated##i.t, cluster(id)
capture ssc install estout
esttab *, se(%9.7f) noomitted drop(0.treated 0.t 0.treated#0.t) modelwidt(15) mtitles label varwidth(35)
Best Answer
There's a user-written panel version of the random effects SUR estimator that you can obtain with
ssc install xtsur
. I am assuming you are using a RE estimator since that is the default withxtreg
. The "add a constant" part is a bit of a hack, and I can't quite tell if it is in fact a bad idea.Here's an toy example of what this would look like:
lincom
would also work here:The coefficients match the output of
xtreg
pretty closely in this case, though they won't be identical: