When we estimate a model like:
\[\text{yield}_{it} = \beta_0 + \beta_1 \text{fertilizer}_{it} + u_{it},\]we often worry about unobserved heterogeneity (recall confounders from Week 8: DAGs). For instance, farmer ability or soil quality might be correlated with both fertilizer use and crop yield. If these unobserved factors are constant over time for each household, we can use panel data to control for them using Fixed Effects.
We will use the maize dataset, eth_allrounds_final, which contains observations for households (hh_id_obs) over multiple survey rounds (wave).
* load dataset and create inputs
use "$data/eth_allrounds_final.dta", clear
keep if crop_name == "MAIZE"
gen fert = nitrogen_kg / plot_area_GPS
* regress pooled OLS (no time controls)
reg yield_kg fert, vce(cluster hh_id_obs)
In all methods below, our goal is to eliminate the unobserved time-invariant household effect $c_i$ from the error term $u_{it} = c_i + \epsilon_{it}$.
First Differencing
The most intuitive way to remove a time-invariant effect $c_i$ is to subtract the previous period’s observation from the current period’s observation. Since $c_i$ does not change over time, $c_i - c_i = 0$.
* sort the panel dataset by household and time
sort hh_id_obs wave
* create first differences for the dependent and independent variables
by hh_id_obs: gen d_yield = yield_kg - yield_kg[_n-1]
by hh_id_obs: gen d_fert = fert - fert[_n-1]
* regress the differenced variables
reg d_yield d_fert, vce(cluster hh_id_obs)
Comparing to the pooled OLS regression above, we see that the coefficient on fertilizer has increased and become statistically significant. This is because we have removed the omitted variable bias caused by the correlation between fertilizer use and farmer ability/soil quality. By regressing the change in yield on the change in fertilizer, we purge any omitted variable bias that is constant over time. Economists call this approach to identification as ``identifying off of within-in variation.’’
Demeaning the Data (Within-Transformation)
If we have more than two time periods, first differencing throws away some information. A more efficient approach is demeaning (also called the within-transformation). Instead of subtracting the previous period, we subtract the household’s average across all periods. Since $c_i$ is constant, its average is just $c_i$, so $c_i - \bar{c_i} = 0$.
* calculate household specific means
bysort hh_id_obs: egen mean_yield = mean(yield_kg)
bysort hh_id_obs: egen mean_fert = mean(fert)
* demean the variables
gen dm_yield = yield_kg - mean_yield
gen dm_fert = fert - mean_fert
* run the regression on demeaned data
reg dm_yield dm_fert, vce(cluster hh_id_obs)
Compared to the first differencing approach, the coefficient on fertilizer has decreased and become slightly less precise. Notice the difference in the number of observations used in the regression. For the FD, there were only 6,410 observations while in the demeaned regression there are 9,964 observations. Despite the small change in coefficient and precision, we are able to keep a lot more of the data when we demean than when we first difference.
Least Squares Dummy Variables (LSDV)
Another way to mathematically achieve the exact same result as demeaning is to include a categorical dummy variable for every single household. This shifts the intercept for each household, effectively absorbing the unobserved $c_i$. This is the Least Squares Dummy Variable (LSDV) approach.
* include household fixed effects via dummy variables using i.
reg yield_kg fert i.hh_id_obs, vce(cluster hh_id_obs)
While LSDV is mathematically identical to the within-transformation, it is computationally intensive (as you just saw!). That is because in this data set there are 3,552 unique households, so Stata has to estimate 3,552 parameters! This will often exceed the matrix limits of your Stata version in addition to taking a very long time to run.
The xtreg, fe Command
Because demeaning requires manual data manipulation and LSDV is computationally slow, Stata provides the xtreg command. You first declare your data to be panel data using xtset, specifying the panel identifier (hh_id_obs) and the time identifier (wave). Then you run xtreg with the fe (fixed effects) option.
* declare panel data structure
xtset hh_id_obs
* estimate the fixed effects model
xtreg yield_kg fert, fe vce(cluster hh_id_obs)
xtreg, fe performs the within-transformation (demeaning) internally behind the scenes. It produces the exact same coefficients as demeaning manually or using LSDV, but it correctly adjusts the degrees of freedom for the standard errors (which manual demeaning gets wrong) and runs much faster than LSDV.
This is the standard, preferred way to run one-way fixed effects models in Stata.
Summary
- One-Way Fixed Effects absorb the unobserved heterogeneity that is constant over time for each panel unit.
- This mechanically eliminates a massive class of potential omitted variable bias.
- Any time-invariant variable drops out, restricting the model to within-unit variation.