Applied Informatics and Computational Economics Lab
28 April 2026
Outline
Background & Theory
Motivation & the panel data advantage
Between and within variation — explained
Literature highlights
The true model & DGP
Mathematical framework
Pooled OLS
Fixed Effects (Within)
Random Effects (GLS)
Estimation, Tests & Applications
Required libraries
Load and explore data
Estimation in R · Python · Stata
Coefficient comparison
Tabular results & LaTeX export
Tests: F-test · Breusch-Pagan LM · Hausman
Variations: clustered SEs · FD · Mundlak
Empirical examples: wagepan · crime4 · jtrain
Further reading & exercises
Where this goes next. This deck estimates one-way entity effects. The companion deck Two-Way Fixed Effects adds the time dimension and the modern difference-in-differences literature built on it. When errors are correlated across units rather than within them, the companion deck Spatial Econometrics supplies the remedy — Conley standard errors and spatial panel models.
Motivation
Why panel data?
Data type
Structure
Limitation
Cross-section
\(N\) units, 1 period
Unit heterogeneity confounds \(X\) effects
Time-series
1 unit, \(T\) periods
No cross-sectional identification
Panel
\(N\) units, \(T\) periods
Controls for unobserved time-invariant effects
Important
The core problem. Each individual carries unobserved, time-invariant traits (\(\alpha_i\) — ability, culture, management quality). If \(\alpha_i\) is correlated with the regressors, OLS is biased. Panel data lets us eliminate\(\alpha_i\).
Running example: wages and education Unobserved ability \(\alpha_i\) is fixed over time but correlates with schooling. A panel differences out \(\alpha_i\), isolating the causal return to education.
🔵 Between variation — differences in time-averaged values across individuals. Are high-\(\bar{x}_i\) individuals also high-\(\bar{y}_i\)? Susceptible to omitted-variable bias when \(\alpha_i \not\perp X\).
🟠 Within variation — deviations of each unit from its own mean over time. Does individual \(i\)’s outcome change when their \(x\) changes? Since \(\alpha_i\) is constant it cancels in the demeaning → free of omitted-variable bias.
Within vs Between — The Key Intuition
Between estimator: Compare entity \(i\) (high average \(\bar{x}_{1,i}\)) to entity \(j\) (low average \(\bar{x}_{1,j}\)):
Cost of FE: uses only within variation. Time-invariant regressors (gender, country, industry) demean to zero and cannot be identified.
Literature Review
Foundational papers
Mundlak (1978) — “On the Pooling of Time-Series and Cross-Section Data.” Econometrica 46(1), 69–85. Showed OLS on panels is biased; introduced correlated RE via auxiliary means regression. DOI: 10.2307/1913646
Hausman (1978) — “Specification Tests in Econometrics.” Econometrica 46(6), 1251–1271. The canonical FE vs. RE test. DOI: 10.2307/1913827
Baltagi (2021) — Econometric Analysis of Panel Data, 6th ed. Springer. Standard reference. DOI: 10.1007/978-3-030-53953-5
Wooldridge (2010) — Econometric Analysis of Cross Section and Panel Data, 2nd ed. MIT Press. Modern asymptotic treatment.
Balestra & Nerlove (1966) — The error-components model that RE estimates. Econometrica 34(3), 585–612. DOI: 10.2307/1909771
Breusch & Pagan (1980) — The LM test used on this deck’s RE slide. Review of Economic Studies 47(1), 239–253. DOI: 10.2307/2297111
Further developments
Arellano & Bond (1991) — GMM for dynamic panels. Review of Economic Studies 58(2), 277–297. DOI: 10.2307/2297968
# Equivalent Python DGP (the CSV is created once by panel-OLS-FE-RE-DGP.R)import numpy as np, pandas as pdGLOBAL_SEED =14159np.random.seed(GLOBAL_SEED)N, T =200, 10b1, b2, sa, se, rho =1.5, 0.8, 1.0, 0.5, 0.6alpha = np.random.normal(0, sa, N)ids = np.repeat(np.arange(1, N+1), T)times = np.tile(np.arange(1, T+1), N)ai = alpha[ids -1]x1 = rho * ai + np.sqrt(1- rho**2) * np.random.normal(0, 1, N*T)x2 = np.random.normal(1, 1.2, N*T)eps = np.random.normal(0, se, N*T)y = ai + b1*x1 + b2*x2 + epsdf_py = pd.DataFrame({"id": ids, "time": times, "y": y, "x1": x1, "x2": x2})df_py.to_csv("../data/panel-OLS-FE-RE.csv", index=False)print(f"Saved: {len(df_py)} obs | β₁={b1}, β₂={b2} | seed={GLOBAL_SEED}")
Code
* Data is already created by panel-OLS-FE-RE-DGP.R* Load and inspect:quietly import delimited "../data/panel-OLS-FE-RE.csv", clearquietly xtset id timextdescribe
id: 1, 2, ..., 200 n = 200
time: 1, 2, ..., 10 T = 10
Delta(time) = 1 unit
Span(time) = 10 periods
(id*time uniquely identifies each observation)
Distribution of T_i: min 5% 25% 50% 75% 95% max
10 10 10 10 10 10 10
Freq. Percent Cum. | Pattern
---------------------------+------------
200 100.00 100.00 | 1111111111
---------------------------+------------
200 100.00 | XXXXXXXXXX
Methodology: Pooled OLS
Ignores panel structure; stacks all \(NT\) observations:
Equivalent to OLS with \(N\) individual dummies. Individual effects are recovered as \(\hat{\alpha}_i = \bar{y}_i - \hat{\beta}_{FE}^\top \bar{\mathbf{x}}_i\).
✓ Consistent even when \(\text{Cov}(\alpha_i, \mathbf{x}_{it}) \neq 0\) ✓ No assumption on the distribution of \(\alpha_i\) ✓ Allows arbitrary correlation between \(\alpha_i\) and \(X_{it}\)
✗ Cannot identify time-invariant regressors ✗ Degrees of freedom: \(NT - N - k\) (loses \(N-1\) df) ✗ Less efficient than RE when RE is valid
Methodology: Random Effects
Assumption:\(\alpha_i \overset{iid}{\sim}(0,\sigma_\alpha^2)\), independent of \(\mathbf{x}_{it}\).
Composite error: \(u_{it} = \alpha_i + \varepsilon_{it}\) with equicorrelated structure:
When \(\theta \to 1\) (large \(T\)): RE \(\to\) FE. When \(\theta \to 0\) (\(\sigma_\alpha^2 \to 0\)): RE \(\to\) OLS. RE uses both within and between variation → more efficient than FE when the RE assumption holds.
import numpy as np # numerical computingimport pandas as pd # data framesimport statsmodels.api as sm # OLS, add_constantfrom scipy.stats import chi2 as chi2_dist # Hausman / LM p-valuesfrom scipy.stats import f as f_dist # F-test p-valuesfrom linearmodels.panel import ( # panel estimators PooledOLS, PanelOLS, RandomEffects, FirstDifferenceOLS, compare)import matplotlib.pyplot as pltimport warnings; warnings.filterwarnings("ignore")print("Python packages loaded successfully.")
Python packages loaded successfully.
* Built-in XT commands* xtset — declare panel structure* xtreg — FE and RE estimation* xtsum — within/between summary statistics* xtdescribe — panel balance check* xttest0 — Breusch-Pagan LM test (after xtreg, re)* hausman — Hausman specification test* User-written (install once)* ssc install require, replace// must come first* ssc install ftools, replace// reghdfe dependency* ssc install reghdfe, replace// fast FE (absorbs high-dim FE)* ssc install estout, replace// esttab, eststo, estadd tables* ssc install coefplot, replace// coefficient plots
Load Data & Descriptive Statistics
df <-read_csv("../data/panel-OLS-FE-RE.csv")pdf <-pdata.frame(df, index =c("id", "time"))summary(df %>% dplyr::select(y, x1, x2))
y x1 x2
Min. :-7.5806 Min. :-3.40133 Min. :-2.6317
1st Qu.:-1.0349 1st Qu.:-0.72173 1st Qu.: 0.1458
Median : 0.6736 Median :-0.06220 Median : 0.9227
Mean : 0.6079 Mean :-0.05822 Mean : 0.9566
3rd Qu.: 2.1846 3rd Qu.: 0.60377 3rd Qu.: 1.7572
Max. : 9.4120 Max. : 3.16117 Max. : 5.0771
for col in ["y", "x1", "x2"]: gm = df_py[col].groupby("id").transform("mean") between = df_py[col].groupby("id").mean().std() within = (df_py[col] - gm).std()print(f"{col:8s}{df_py[col].std():8.4f}{between:8.4f}{within:8.4f}")
quietly import delimited "../data/panel-OLS-FE-RE.csv", clearquietly xtset id timextsumy x1 x2
Variable | Mean Std. dev. Min Max | Observations
-----------------+--------------------------------------------+----------------
y overall | .6078702 2.485512 -7.580562 9.41196 | N = 2000
between | 1.91067 -3.961439 6.571817 | n = 200
within | 1.59485 -5.004289 6.387262 | T = 10
| |
x1 overall | -.058221 1.004421 -3.401333 3.161175 | N = 2000
between | .6254248 -1.417901 1.896193 | n = 200
within | .7870617 -3.013855 2.834897 | T = 10
| |
x2 overall | .9566371 1.218078 -2.631657 5.077078 | N = 2000
between | .34883 .1392908 1.868303 | n = 200
within | 1.167296 -3.00237 4.975022 | T = 10
Note
For \(x_1\): the between SD is driven by \(\rho \cdot \alpha_i\) — this is what creates the endogeneity. The within SD comes from the idiosyncratic component \(\sqrt{1-\rho^2}\,u_{it}\). This is exactly why FE and OLS give different answers for \(\beta_1\).
Pooled OLS Estimation
ols_r <-lm(y ~ x1 + x2, data = df)summary(ols_r)
Call:
lm(formula = y ~ x1 + x2, data = df)
Residuals:
Min 1Q Median 3Q Max
-3.4951 -0.6423 -0.0024 0.6405 3.4087
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.03580 0.02706 -1.323 0.186
x1 2.06298 0.02116 97.474 <2e-16 ***
x2 0.79840 0.01745 45.748 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.9504 on 1997 degrees of freedom
Multiple R-squared: 0.8539, Adjusted R-squared: 0.8538
F-statistic: 5837 on 2 and 1997 DF, p-value: < 2.2e-16
OLS attributes part of \(\text{Cov}(x_1, \alpha_i)\) to the coefficient. High-\(\alpha_i\) individuals tend to have high \(x_1\) (\(\rho=0.6\)), so OLS confounds individual ability with \(x_1\)’s effect.
Note
Why is \(\hat{\beta}_2\) unaffected?
\(x_2 \perp \alpha_i\) by construction. All three estimators are consistent for \(\beta_2 = 0.8\).
print("Decision:", "Reject H₀ → FE preferred"if p_F <0.05else"Do not reject H₀")
Decision: Reject H₀ → FE preferred
quietly import delimited "../data/panel-OLS-FE-RE.csv", clearquietly xtset id time* The F-test appears automatically at the bottom ofxtreg, fe outputxtregy x1 x2, fe* "F test that all u_i=0: F(N-1, NT-N-k) Prob > F = ..."
Fixed-effects (within) regression Number of obs = 2,000
Group variable: id Number of groups = 200
R-squared: Obs per group:
Within = 0.9166 min = 10
Between = 0.9363 avg = 10.0
Overall = 0.8382 max = 10
F(2, 1798) = 9885.30
corr(u_i, Xb) = 0.4682 Prob > F = 0.0000
------------------------------------------------------------------------------
y | Coefficient Std. err. t P>|t| [95% conf. interval]
-------------+----------------------------------------------------------------
x1 | 1.50115 .0138017 108.77 0.000 1.474081 1.528219
x2 | .8040246 .0093059 86.40 0.000 .785773 .8222762
_cons | -.073891 .0140755 -5.25 0.000 -.1014971 -.0462848
-------------+----------------------------------------------------------------
sigma_u | 1.0066421
sigma_e | .48552911
rho | .81126828 (fraction of variance due to u_i)
------------------------------------------------------------------------------
F test that all u_i=0: F(199, 1798) = 29.42 Prob > F = 0.0000
Breusch-Pagan LM Test — Theory
Null hypothesis: no random individual effects (pooled OLS is sufficient)
Why needed: under \(H_0\) both FE and RE are consistent (use RE — more efficient); under \(H_1\) only FE is consistent. The test compares the two estimates directly.
Reject when:\(H > \chi^2_{1-\alpha}(k)\) — the FE and RE estimates diverge systematically → use FE.
Hausman Specification Test — Code
phtest(fe_r, re_r)
Hausman Test
data: y ~ x1 + x2
chisq = 198.93, df = 2, p-value < 2.2e-16
alternative hypothesis: one model is inconsistent
---- Coefficients ----
| (b) (B) (b-B) sqrt(diag(V_b-V_B))
| FE_h RE_h Difference Std. err.
-------------+----------------------------------------------------------------
x1 | 1.50115 1.609284 -.1081338 .0044752
x2 | .8040246 .8021588 .0018658 .0011782
------------------------------------------------------------------------------
b = Consistent under H0 and Ha; obtained from xtreg.
B = Inconsistent under Ha, efficient under H0; obtained from xtreg.
Test of H0: Difference in coefficients not systematic
chi2(2) = (b-B)'[(V_b-V_B)^(-1)](b-B)
= 585.84
Prob > chi2 = 0.0000
Test Summary
Test
H0
Statistic
p-value
Decision
F-test for FE
All \(\alpha_i\) equal (OLS ok)
29.417
<2e-16
Reject → FE
Breusch-Pagan LM
\(\sigma^2_\alpha = 0\) (OLS ok)
2234.492
<2e-16
Reject → RE/FE
Hausman
\(\text{Cov}(\alpha_i, X) = 0\) (RE consistent)
198.932
<2e-16
Reject → FE
Important
All three tests point to the same conclusion: use Fixed Effects. Individual effects are significant and correlated with \(X_{it}\); the RE assumption is violated. \(\hat{\beta}_1^{FE} \approx 1.501 \approx \beta_1^{true} = 1.5\) ✓
Variation: Clustered Standard Errors
Classical FE SEs assume \(\varepsilon_{it}\) is iid. In practice, errors are often serially correlated within individuals. Cluster-robust SEs correct for this.
* Stata reads the original .dta files from the Boston College archivequietlyuse"http://fmwww.bc.edu/ec-p/data/wooldridge/wagepan.dta", clearquietlyuse"http://fmwww.bc.edu/ec-p/data/wooldridge/crime4.dta", clearquietlyuse"http://fmwww.bc.edu/ec-p/data/wooldridge/jtrain.dta", cleardescribe, short
Contains data from http://fmwww.bc.edu/ec-p/data/wooldridge/jtrain.dta
Observations: 471
Variables: 30 26 Jan 2000 12:16
Sorted by:
Research question: What is the wage premium from joining a union, controlling for individual ability?
The endogeneity problem. Union membership is not randomly assigned. Workers with higher unobservable productivity — motivation, reliability, cognitive skill — are more likely to join (or be accepted by) unions and earn higher wages regardless of union status. A naive cross-sectional regression conflates the union wage effect with the selection effect:
Panel solution. With repeated observations of the same worker, we can difference out \(\alpha_i\) (time-invariant ability). Fixed Effects identifies the union premium only from workers who change union status over the panel — a within-person comparison free of selection bias.
Tip
Wooldridge reference: Table 14.2, p. 484 (7th ed.). The OLS union premium (≈ 18%) drops by more than half under FE (≈ 8%), a concrete illustration of ability bias.
Source: National Longitudinal Survey of Young Men (NLSY), 1980–1987. Structure: Balanced panel — \(N = 545\) men, \(T = 8\) years, \(NT = 4{,}360\) observations.
Variable
Description
Type
nr
Individual identifier
ID
year
Survey year (1980–1987)
Time
lwage
Log hourly wage (outcome)
Continuous
union
= 1 if union member
Time-varying
married
= 1 if married
Time-varying
exper, expersq
Experience (years) & its square
Time-varying
educ
Years of schooling
Time-invariant
black, hisp
Race/ethnicity indicators
Time-invariant
d81–d87
Year dummies (base = 1980)
Time fixed effects
Warning
educ, black, and hisp are time-invariant — Fixed Effects cannot identify their coefficients (they are absorbed into \(\hat{\alpha}_i\)). Only OLS and RE can estimate them.
Research question: Does increasing police presence reduce crime, and by how much?
The endogeneity problem. Police are deployed in response to crime: counties with chronically high crime rates hire more officers. This reverse causality means Pooled OLS will show a positive correlation between police and crime — the opposite of the deterrence effect. Time-invariant county characteristics (geography, population density, culture, historical crime patterns) compound the problem.
\[\underbrace{\text{Cov}(polpc_{it},\, \alpha_i)}_{\text{high-crime counties hire more police}} \neq 0 \implies \hat{\beta}^{OLS}_{polpc} \text{ is biased upward (or even sign-reversed)}\]
Panel solution. County fixed effects absorb all time-invariant characteristics. The within-county variation in policing over time, after controlling for economic conditions, identifies the deterrence effect free of cross-sectional confounding.
Tip
Wooldridge reference: Table 13.3, p. 438 (7th ed.). The OLS coefficient on lpolpc is positive; the FE coefficient changes markedly — an illustration of omitted variable bias from stable county characteristics.
Source: Cornwell & Trumbull (1994), North Carolina county crime data. Structure: Balanced panel — \(N = 90\) counties, \(T = 7\) years (1981–1987), \(NT = 630\) observations.
Variable
Description
Type
county
County identifier
ID
year
Year (1981–1987)
Time
lcrmrte
Log crime rate per person (outcome)
Continuous
lpolpc
Log police per capita
Time-varying
ldensity
Log population density
Mostly time-invariant
lwcon
Log weekly wage in construction
Time-varying
lwser
Log weekly wage in services
Time-varying
lwtrd
Log weekly wage in trade
Time-varying
d82–d87
Year dummies (base = 1981)
Time fixed effects
Economic intuition: wage variables capture the opportunity cost of crime (higher wages → higher cost of incarceration → less crime). County fixed effects capture all time-invariant characteristics: geography, culture, historical crime environment.
Identification in FE comes from within-county changes in police staffing over time — a policy-relevant source of variation free of cross-sectional selection.
Research question: Does government-funded job training reduce production defects (scrap)?
The endogeneity problem. Grant receipt is not random. Two opposing selection mechanisms may operate simultaneously:
Negative selection: poorly-performing firms are targeted for grants (or more likely to apply for remedial training) → \(\text{Cov}(grant_{it}, \alpha_i) < 0\) → OLS under-estimates the training effect
Positive selection: better-managed firms have the administrative capacity to apply for grants → \(\text{Cov}(grant_{it}, \alpha_i) > 0\) → OLS over-estimates the effect
Without knowing which dominates, OLS is unreliable in either direction.
Panel solution. Firm fixed effects absorb management quality (\(\alpha_i\)). The within-firm change in scrap rate after receiving a grant — compared to the same firm before — identifies the causal training effect.
Tip
Wooldridge reference: Table 13.8, p. 444 (7th ed.). \(T = 3\) (1987–1989), \(N = 54\) firms with complete lscrap data. The FE estimate of grant is negative and substantially larger in magnitude than OLS.
Source: Holzer et al. (1993), Michigan manufacturing firms. Structure: Unbalanced panel (after dropping missing lscrap) — \(T = 3\) years (1987–1989), \(N = 54\) firms with complete scrap data.
Variable
Description
Type
fcode
Firm identifier
ID
year
Survey year (1987–1989)
Time
lscrap
Log scrap rate (defects per 100 items, outcome)
Continuous
grant
= 1 if firm received training grant this year
Time-varying
grant_1
= 1 if firm received grant in previous year
Time-varying
d88, d89
Year dummies (base = 1987)
Time fixed effects
Warning
lscrap has many missing values — only firms that voluntarily reported scrap rates are included. This selective reporting may introduce attrition bias; results should be interpreted cautiously.
Expected sign:\(\beta_1 < 0\) — training reduces defects (lower scrap = higher productivity). \(\beta_2 \leq 0\) — any lagged effect of prior-year grant.
quietlyuse"http://fmwww.bc.edu/ec-p/data/wooldridge/wagepan.dta", clearquietly xtset nryearxtreg lwage union married exper expersq educ black hisp d81 d82 d83 d84 d85 d86 d87, fe* Note: educ black hisp are dropped (time-invariant within person)estimatesstore FE_w
note: educ omitted because of collinearity.
note: black omitted because of collinearity.
note: hisp omitted because of collinearity.
note: d87 omitted because of collinearity.
Fixed-effects (within) regression Number of obs = 4,360
Group variable: nr Number of groups = 545
R-squared: Obs per group:
Within = 0.1806 min = 8
Between = 0.0005 avg = 8.0
Overall = 0.0635 max = 8
F(10, 3805) = 83.85
corr(u_i, Xb) = -0.1212 Prob > F = 0.0000
------------------------------------------------------------------------------
lwage | Coefficient Std. err. t P>|t| [95% conf. interval]
-------------+----------------------------------------------------------------
union | .0800019 .0193103 4.14 0.000 .0421423 .1178614
married | .0466804 .0183104 2.55 0.011 .0107812 .0825796
exper | .1321464 .0098247 13.45 0.000 .1128842 .1514087
expersq | -.0051855 .0007044 -7.36 0.000 -.0065666 -.0038044
educ | 0 (omitted)
black | 0 (omitted)
hisp | 0 (omitted)
d81 | .0190448 .0203626 0.94 0.350 -.0208779 .0589674
d82 | -.011322 .0202275 -0.56 0.576 -.0509798 .0283359
d83 | -.0419955 .0203205 -2.07 0.039 -.0818357 -.0021553
d84 | -.0384709 .0203144 -1.89 0.058 -.0782991 .0013573
d85 | -.0432498 .0202458 -2.14 0.033 -.0829434 -.0035563
d86 | -.027382 .0203863 -1.34 0.179 -.0673511 .0125872
d87 | 0 (omitted)
_cons | 1.02764 .0299499 34.31 0.000 .9689201 1.086359
-------------+----------------------------------------------------------------
sigma_u | .40092789
sigma_e | .35099001
rho | .56612235 (fraction of variance due to u_i)
------------------------------------------------------------------------------
F test that all u_i=0: F(544, 3805) = 9.64 Prob > F = 0.0000
F test for individual effects
data: lwage ~ union + married + exper + expersq + educ + black + hisp + ...
F = 8.023, df1 = 540, df2 = 3805, p-value < 2.2e-16
alternative hypothesis: significant effects
print("Decision:", "Reject H0 → FE preferred"if p_Fw <0.05else"Do not reject H0")
Decision: Reject H0 → FE preferred
quietlyuse"http://fmwww.bc.edu/ec-p/data/wooldridge/wagepan.dta", clearquietly xtset nryearxtreg lwage union married exper expersq educ black hisp d81 d82 d83 d84 d85 d86 d87, fe* "F test that all u_i=0" appears at the bottom of the output
note: educ omitted because of collinearity.
note: black omitted because of collinearity.
note: hisp omitted because of collinearity.
note: d87 omitted because of collinearity.
Fixed-effects (within) regression Number of obs = 4,360
Group variable: nr Number of groups = 545
R-squared: Obs per group:
Within = 0.1806 min = 8
Between = 0.0005 avg = 8.0
Overall = 0.0635 max = 8
F(10, 3805) = 83.85
corr(u_i, Xb) = -0.1212 Prob > F = 0.0000
------------------------------------------------------------------------------
lwage | Coefficient Std. err. t P>|t| [95% conf. interval]
-------------+----------------------------------------------------------------
union | .0800019 .0193103 4.14 0.000 .0421423 .1178614
married | .0466804 .0183104 2.55 0.011 .0107812 .0825796
exper | .1321464 .0098247 13.45 0.000 .1128842 .1514087
expersq | -.0051855 .0007044 -7.36 0.000 -.0065666 -.0038044
educ | 0 (omitted)
black | 0 (omitted)
hisp | 0 (omitted)
d81 | .0190448 .0203626 0.94 0.350 -.0208779 .0589674
d82 | -.011322 .0202275 -0.56 0.576 -.0509798 .0283359
d83 | -.0419955 .0203205 -2.07 0.039 -.0818357 -.0021553
d84 | -.0384709 .0203144 -1.89 0.058 -.0782991 .0013573
d85 | -.0432498 .0202458 -2.14 0.033 -.0829434 -.0035563
d86 | -.027382 .0203863 -1.34 0.179 -.0673511 .0125872
d87 | 0 (omitted)
_cons | 1.02764 .0299499 34.31 0.000 .9689201 1.086359
-------------+----------------------------------------------------------------
sigma_u | .40092789
sigma_e | .35099001
rho | .56612235 (fraction of variance due to u_i)
------------------------------------------------------------------------------
F test that all u_i=0: F(544, 3805) = 9.64 Prob > F = 0.0000
pFtest(fe_c, ols_c)
F test for individual effects
data: lcrmrte ~ lpolpc + ldensity + lwcon + lwser + lwtrd + d82 + d83 + ...
F = 41.375, df1 = 89, df2 = 529, p-value < 2.2e-16
alternative hypothesis: significant effects
print("Decision:", "Reject H0 → FE preferred"if p_Fc <0.05else"Do not reject H0")
Decision: Reject H0 → FE preferred
quietlyuse"http://fmwww.bc.edu/ec-p/data/wooldridge/crime4.dta", clearquietly xtset county yearxtreg lcrmrte lpolpc ldensity lwcon lwser lwtrd d82 d83 d84 d85 d86 d87, fe* "F test that all u_i=0" appears at the bottom of the output
Fixed-effects (within) regression Number of obs = 630
Group variable: county Number of groups = 90
R-squared: Obs per group:
Within = 0.2364 min = 7
Between = 0.4914 avg = 7.0
Overall = 0.4657 max = 7
F(11, 529) = 14.89
corr(u_i, Xb) = -0.5693 Prob > F = 0.0000
------------------------------------------------------------------------------
lcrmrte | Coefficient Std. err. t P>|t| [95% conf. interval]
-------------+----------------------------------------------------------------
lpolpc | .2390231 .0262491 9.11 0.000 .1874579 .2905882
ldensity | .8328452 .3235439 2.57 0.010 .1972567 1.468434
lwcon | -.0420775 .0457208 -0.92 0.358 -.1318941 .0477392
lwser | .0153567 .0224434 0.68 0.494 -.0287325 .0594459
lwtrd | -.0251048 .0475971 -0.53 0.598 -.1186072 .0683977
d82 | -.0049135 .0243685 -0.20 0.840 -.0527844 .0429575
d83 | -.1040681 .0254086 -4.10 0.000 -.1539824 -.0541539
d84 | -.1652527 .028622 -5.77 0.000 -.2214793 -.109026
d85 | -.1720682 .0314085 -5.48 0.000 -.2337688 -.1103675
d86 | -.1112502 .0338068 -3.29 0.001 -.1776622 -.0448382
d87 | -.0460723 .0377466 -1.22 0.223 -.1202239 .0280793
_cons | -1.679477 .3955793 -4.25 0.000 -2.456576 -.9023778
-------------+----------------------------------------------------------------
sigma_u | .47881132
sigma_e | .16114885
rho | .89825244 (fraction of variance due to u_i)
------------------------------------------------------------------------------
F test that all u_i=0: F(89, 529) = 41.38 Prob > F = 0.0000
pFtest(fe_j, ols_j)
F test for individual effects
data: lscrap ~ grant + grant_1 + d88 + d89
F = 24.661, df1 = 53, df2 = 104, p-value < 2.2e-16
alternative hypothesis: significant effects
print("Decision:", "Reject H0 → FE preferred"if p_Fj <0.05else"Do not reject H0")
Decision: Reject H0 → FE preferred
quietlyuse"http://fmwww.bc.edu/ec-p/data/wooldridge/jtrain.dta", clearquietlykeepif !missing(lscrap)quietly xtset fcode yearxtreg lscrap grant grant_1 d88 d89, fe* "F test that all u_i=0" appears at the bottom of the output
Fixed-effects (within) regression Number of obs = 162
Group variable: fcode Number of groups = 54
R-squared: Obs per group:
Within = 0.2010 min = 3
Between = 0.0079 avg = 3.0
Overall = 0.0068 max = 3
F(4, 104) = 6.54
corr(u_i, Xb) = -0.0714 Prob > F = 0.0001
------------------------------------------------------------------------------
lscrap | Coefficient Std. err. t P>|t| [95% conf. interval]
-------------+----------------------------------------------------------------
grant | -.2523149 .150629 -1.68 0.097 -.5510178 .046388
grant_1 | -.4215895 .2102 -2.01 0.047 -.8384239 -.0047551
d88 | -.0802157 .1094751 -0.73 0.465 -.2973089 .1368776
d89 | -.2472028 .1332183 -1.86 0.066 -.5113797 .016974
_cons | .597434 .0677344 8.82 0.000 .4631142 .7317539
-------------+----------------------------------------------------------------
sigma_u | 1.438982
sigma_e | .4977442
rho | .89313867 (fraction of variance due to u_i)
------------------------------------------------------------------------------
F test that all u_i=0: F(53, 104) = 24.66 Prob > F = 0.0000
Hausman Test
data: lwage ~ union + married + exper + expersq + educ + black + hisp + ...
chisq = 28.597, df = 10, p-value = 0.001448
alternative hypothesis: one model is inconsistent
print("Decision:", "Reject H0 → use FE"if p_Hw <0.05else"Cannot reject H0 → RE preferred")
Decision: Reject H0 → use FE
quietlyuse"http://fmwww.bc.edu/ec-p/data/wooldridge/wagepan.dta", clearquietly xtset nryearquietlyxtreg lwage union married exper expersq educ black hisp d81 d82 d83 d84 d85 d86 d87, feestimatesstore FE_whquietlyxtreg lwage union married exper expersq educ black hisp d81 d82 d83 d84 d85 d86 d87, reestimatesstore RE_whhausman FE_wh RE_wh, sigmamore
Note: the rank of the differenced variance matrix (5) does not equal the number of coefficients being tested (10); be
sure this is what you expect, or there may be problems computing the test. Examine the output of your
estimators for anything unexpected and possibly consider scaling your variables so that the coefficients are on
a similar scale.
---- Coefficients ----
| (b) (B) (b-B) sqrt(diag(V_b-V_B))
| FE_wh RE_wh Difference Std. err.
-------------+----------------------------------------------------------------
union | .0800019 .1061344 -.0261326 .0074922
married | .0466804 .063986 -.0173057 .0074632
exper | .1321464 .1057545 .0263919 .
expersq | -.0051855 -.0047239 -.0004616 .0001533
d81 | .0190448 .040462 -.0214172 .
d82 | -.011322 .0309212 -.0422431 .
d83 | -.0419955 .0202806 -.0622761 .
d84 | -.0384709 .0431187 -.0815896 .
d85 | -.0432498 .0578154 -.1010653 .
d86 | -.027382 .0919475 -.1193295 .
------------------------------------------------------------------------------
b = Consistent under H0 and Ha; obtained from xtreg.
B = Inconsistent under Ha, efficient under H0; obtained from xtreg.
Test of H0: Difference in coefficients not systematic
chi2(5) = (b-B)'[(V_b-V_B)^(-1)](b-B)
= 26.22
Prob > chi2 = 0.0001
(V_b-V_B is not positive definite)
phtest(fe_c, re_c)
Hausman Test
data: lcrmrte ~ lpolpc + ldensity + lwcon + lwser + lwtrd + d82 + d83 + ...
chisq = 5.1003, df = 11, p-value = 0.9262
alternative hypothesis: one model is inconsistent
Note: the rank of the differenced variance matrix (5) does not equal the number of coefficients being tested (11); be
sure this is what you expect, or there may be problems computing the test. Examine the output of your
estimators for anything unexpected and possibly consider scaling your variables so that the coefficients are on
a similar scale.
---- Coefficients ----
| (b) (B) (b-B) sqrt(diag(V_b-V_B))
| FE_ch RE_ch Difference Std. err.
-------------+----------------------------------------------------------------
lpolpc | .2390231 .2269914 .0120317 .0072805
ldensity | .8328452 .5008089 .3320363 .3189682
lwcon | -.0420775 -.0365123 -.0055651 .0070562
lwser | .0153567 .0137203 .0016365 .002074
lwtrd | -.0251048 -.0214237 -.0036811 .0061277
d82 | -.0049135 -.0021891 -.0027243 .0032979
d83 | -.1040681 -.0973936 -.0066746 .0064522
d84 | -.1652527 -.1543893 -.0108634 .011117
d85 | -.1720682 -.1573731 -.014695 .0150724
d86 | -.1112502 -.0943217 -.0169284 .017992
d87 | -.0460723 -.0256671 -.0204051 .0215033
------------------------------------------------------------------------------
b = Consistent under H0 and Ha; obtained from xtreg.
B = Inconsistent under Ha, efficient under H0; obtained from xtreg.
Test of H0: Difference in coefficients not systematic
chi2(5) = (b-B)'[(V_b-V_B)^(-1)](b-B)
= 5.09
Prob > chi2 = 0.4054
(V_b-V_B is not positive definite)
phtest(fe_j, re_j)
Hausman Test
data: lscrap ~ grant + grant_1 + d88 + d89
chisq = 2.1425, df = 4, p-value = 0.7096
alternative hypothesis: one model is inconsistent
Note: the rank of the differenced variance matrix (2) does not equal the number of coefficients being tested (4); be
sure this is what you expect, or there may be problems computing the test. Examine the output of your
estimators for anything unexpected and possibly consider scaling your variables so that the coefficients are on
a similar scale.
---- Coefficients ----
| (b) (B) (b-B) sqrt(diag(V_b-V_B))
| FE_jh RE_jh Difference Std. err.
-------------+----------------------------------------------------------------
grant | -.2523149 -.2144354 -.0378795 .030201
grant_1 | -.4215895 -.3728755 -.048714 .046283
d88 | -.0802157 -.0935436 .013328 .0106263
d89 | -.2472028 -.2713577 .0241548 .0217557
------------------------------------------------------------------------------
b = Consistent under H0 and Ha; obtained from xtreg.
B = Inconsistent under Ha, efficient under H0; obtained from xtreg.
Test of H0: Difference in coefficients not systematic
chi2(2) = (b-B)'[(V_b-V_B)^(-1)](b-B)
= 2.05
Prob > chi2 = 0.3593
Interpretation. The OLS union wage premium (18.2%) is substantially above the FE estimate (8%). Workers with higher unobservable productivity — motivation, reliability — are more likely to join unions and earn higher wages regardless. OLS conflates this selection with the causal premium. Fixed Effects identifies the effect solely from workers who change union status, removing all time-invariant confounders including ability. The Hausman test rejects the RE assumption, confirming endogeneity. Note that educ, black, and hisp are absorbed into \(\hat{\alpha}_i\) under FE and cannot be separately identified.
\[\widehat{\log(crmrte)}^{RE}_{it} = \underset{(0.025)}{0.227}\,\log(polpc)_{it} + \ldots \quad \text{(close to FE; Hausman does not reject)}\]
Interpretation. The positive coefficient on log police per capita in all specifications is a textbook illustration of reverse causality: police staffing responds to crime, so even the within-county variation is contaminated — more police this year is a response to more crime this year. FE removes the time-invariant part of the county confounding (crime culture, geography, urbanisation), but simultaneity survives demeaning; a full causal analysis requires instrumental variables (as Cornwell & Trumbull 1994 do). The economically sensible results are the wage coefficients: under FE the construction and trade wage coefficients turn negative, consistent with the opportunity-cost-of-crime hypothesis. In this specification the Hausman test does not reject RE (p ≈ 0.41 in Stata, 0.93 in R) — FE and RE estimates are close, so the county effects are only weakly correlated with these regressors.
Interpretation. The FE estimate of \(-0.252\) implies that receiving a job training grant reduces the scrap rate by approximately 22.3% (\(e^{-0.252} - 1 \approx -22.3\)%), a meaningful improvement in production quality. The OLS estimate (\(+0.200\)) even has the wrong sign, consistent with negative selection: firms that apply for grants tend to be below-average performers, causing OLS to under-estimate (here, sign-reverse) the true effect. Firm fixed effects remove this confounding, isolating the genuine within-firm improvement attributable to training. The small panel (\(T = 3\)) limits statistical power, but the direction and magnitude are consistent with the programme’s objective. Note that the lagged grant coefficient (\(-0.422\)) captures a persistent productivity gain from prior-year training.
Exercises — Estimation
Zero endogeneity. Set rho = 0 in the DGP. Re-estimate OLS, FE, RE. Do the three estimators converge? Does the Hausman test still reject?
Bias vs. ρ. Loop over \(\rho \in \{0, 0.2, 0.4, 0.6, 0.8\}\). Record the bias of \(\hat{\beta}_1\) for each estimator. Plot bias vs. \(\rho\) and interpret.
Unbalanced panel. Randomly drop 20% of observations to create an unbalanced panel. Re-run all models. Do estimates and test conclusions change?
Time-invariant regressor. Add \(z_i \sim \mathcal{N}(0,1)\) (time-invariant) to the DGP. What happens when you run FE? Why? How does RE handle it?
Increasing T. Fix \(N=100\), \(\rho=0.6\). Run RE for \(T \in \{2, 5, 10, 20, 50\}\). How does the RE bias for \(\beta_1\) change as \(T\) grows? (Hint: what happens to \(\theta\)?)
Exercises — Testing
Mundlak equivalence. Verify numerically that \(\hat{\beta}_1\) and \(\hat{\beta}_2\) from the Mundlak model equal the FE estimates. Why does this hold?
Serial correlation in errors. Modify the DGP so \(\varepsilon_{it} = 0.7\varepsilon_{i,t-1} + \eta_{it}\) (AR(1)). Compare classical FE SEs to cluster-robust SEs. How large is the discrepancy?
Hausman by hand. Recompute the Hausman statistic manually from the FE and RE coefficient vectors and covariance matrices; confirm it matches phtest() / hausman.
BP LM on the examples. For each Wooldridge example, verify that the LM statistic computed from pooled OLS residuals matches plmtest() and Stata’s xttest0.
Dynamic panel (reading). Add \(y_{i,t-1}\) as a regressor. Why does FE produce biased estimates (Nickell bias)? Read Arellano & Bond (1991) and explain the GMM approach in two sentences.
Further Reading
Textbooks
Baltagi (2021) — Econometric Analysis of Panel Data, 6th ed. Springer. Definitive reference covering all estimators and tests. DOI: 10.1007/978-3-030-53953-5
Wooldridge (2010) — Econometric Analysis of Cross Section and Panel Data, 2nd ed. MIT Press. Rigorous modern treatment.