The examples use the Cornwell–Rupert PSID Males Wages Panel (Vella & Verbeek 1998), available as Males in R’s plm package: 545 male workers observed annually from 1980 to 1987 (N = 4,360, balanced panel).
Variable
Type
Description
wage
Time-varying
Log hourly wage (outcome)
exper
Time-varying
Years of work experience
union_d
Time-varying
Union member (1 = yes)
married_d
Time-varying
Married (1 = yes)
health_d
Time-varying
Poor health (1 = yes)
school
Time-invariant
Years of schooling
black_d
Time-invariant
Black ethnicity (1 = yes)
hisp_d
Time-invariant
Hispanic ethnicity (1 = yes)
The central research question is: how does work experience relate to log wages? We distinguish the within-person effect (does your wage grow as you gain experience year by year?) from the between-person effect (do workers with more average experience earn more?).
library(lme4) # mixed-effects modelslibrary(plm) # panel FE / REdata("Males", package ="plm")d <- Malesd$id <- d$nrd$union_d <-as.integer(d$union =="yes")d$married_d <-as.integer(d$married =="yes")d$health_d <-as.integer(d$health =="yes")d$black_d <-as.integer(d$ethn =="black")d$hisp_d <-as.integer(d$ethn =="hisp")# Decompose experience into within and between componentsd$exper_bar <-ave(d$exper, d$id) # person-specific meand$exper_win <- d$exper - d$exper_bar # deviation from own meanpdat <-pdata.frame(d, index =c("id", "year"))cat(sprintf("Individuals: %d | Years: 1980–1987 | N: %d\n",length(unique(d$id)), nrow(d)))
Individuals: 545 | Years: 1980–1987 | N: 4360
/* males_wages.csv should be in your working directory. *//* Alternatively: webuse nlswork, clear *//* (then rename: ln_wage→wage, ttl_exp→exper, grade→school) */import delimited using"males_wages.csv", clearxtset id yearlabelvariable wage "Log wage"labelvariable exper "Work experience (years)"labelvariable school "Years of schooling (time-invariant)"/* Decompose experience into within and between components */bysort id: egen exper_bar = mean(exper)gen exper_win = exper - exper_barlabelvariable exper_bar "Person mean of experience (between)"labelvariable exper_win "exper minus person mean (within)"di"Individuals: 545 | Years: 1980-1987 | N: " _N
regress wage exper school union_d married_d health_d black_d hisp_d
Model 2 — Fixed Effects
Within-group demeaning eliminates all between-person variation. Time-invariant variables (school, black_d, hisp_d) are absorbed by the person dummies and cannot be estimated.
/* school, black_d, hisp_d cannot be included -- time-invariant */xtreg wage exper union_d married_d health_d, fe
Model 3 — Standard Random Effects
Assumes the within and between effects of experience are equal (\(\beta_W = \beta_B\)). The Hausman-style test below shows this assumption is rejected.
xtreg wage exper school union_d married_d health_d black_d hisp_d, re
Hausman-Style Test
The test checks whether the within and between effects of experience differ — i.e., whether the contextual effect \(\beta_{2C} = 0\). A significant result means the two effects are distinct and standard RE produces an uninterpretable blend.
m_rewb_h <-lmer(wage ~ exper_win + exper_bar + school + union_d + married_d + health_d + black_d + hisp_d + (1| id),data = d, REML =FALSE)lrt <-anova(m_re, m_rewb_h)data.frame(Test ="LRT: Standard RE vs REWB",`Chi-sq`=round(lrt$Chisq[2], 3),df =1,`p-value`=round(lrt$`Pr(>Chisq)`[2], 4),Conclusion =ifelse(lrt$`Pr(>Chisq)`[2] <0.05,"Reject H₀: within ≠ between → use REWB","Cannot reject H₀: standard RE acceptable"),check.names =FALSE) |>kable()
Test
Chi-sq
df
p-value
Conclusion
LRT: Standard RE vs REWB
5.122
1
0.0236
Reject H₀: within ≠ between → use REWB
quietlyxtreg wage exper union_d married_d health_d, feestimatesstore fe_storedquietlyxtreg wage exper school union_d married_d health_d black_d hisp_d, rehausman fe_stored ., sigmamore/* Significant result => within ≠ between => use REWB */
Model 4 — Within-Between RE (REWB)
The recommended model. exper_win captures the within-person effect of gaining experience year by year; exper_bar captures the between-person effect of having more average experience. Time-invariant variables are estimable — a key advantage over FE.
/* exper_win and exper_bar computed earlier via: *//* bysort id: egen exper_bar = mean(exper) *//* gen exper_win = exper - exper_bar */mixed wage exper_win exper_bar school /// union_d married_d health_d black_d hisp_d || id:, reml
Model 5 — Mundlak Parameterisation
Algebraically equivalent to REWB. Uses raw exper rather than the demeaned form, and adds exper_bar as a control. The coefficient on exper is the within effect \(\hat{\beta}_W\); the coefficient on exper_bar is the contextual effect \(\hat{\beta}_{2C}\).
The identity \(\hat{\beta}_W + \hat{\beta}_{2C} = \hat{\beta}_{2B}\) (REWB between effect) must hold exactly.
xtreg wage exper exper_bar school /// union_d married_d health_d black_d hisp_d, re/* Verify identity manually: */scalar bW = _b[exper]scalar b2C = _b[exper_bar]di"beta_W + beta_2C = " bW + b2C/* Compare with beta_2B from the REWB mixed model above */
Model 6 — REWB with Random Slopes
Allows the within-experience effect to vary across individuals. Bell et al. (2019, Section 4.1, Figure 1) show that omitting random slopes when they exist in the true DGP produces anti-conservative standard errors in both FE and RE models.
make_row <-function(model, w, b, sch, blk) {data.frame(Model = model,`exper within`=round(w, 4),`exper between`=if (is.na(b)) NAelseround(b, 4),school =if (is.na(sch)) NAelseround(sch, 4),black_d =if (is.na(blk)) NAelseround(blk, 4),check.names =FALSE)}summary_tbl <-rbind(make_row("OLS",coef(m_ols)["exper"], NA,coef(m_ols)["school"],coef(m_ols)["black_d"]),make_row("Fixed Effects",as.numeric(coef(m_fe)["exper"]), NA, NA, NA),make_row("Standard RE",fixef(m_re)["exper"], NA,fixef(m_re)["school"],fixef(m_re)["black_d"]),make_row("REWB",fixef(m_rewb)["exper_win"],fixef(m_rewb)["exper_bar"],fixef(m_rewb)["school"],fixef(m_rewb)["black_d"]),make_row("Mundlak",fixef(m_mndl)["exper"],fixef(m_mndl)["exper_bar"],fixef(m_mndl)["school"],fixef(m_mndl)["black_d"]),make_row("REWB + Random Slopes",fixef(m_rs)["exper_win"],fixef(m_rs)["exper_bar"],fixef(m_rs)["school"],fixef(m_rs)["black_d"]))summary_tbl |>kable(caption ="Key coefficients across models. FE cannot estimate time-invariant variables.",col.names =c("Model", "exper (within/blend)","exper_bar (between/contextual)","school", "black_d"),align ="lcccc" ) |>kable_styling(full_width =FALSE) |>row_spec(4, bold =TRUE, background ="#f0f8ff") |>add_footnote(c("OLS and Std RE: exper coefficient blends within and between effects.","FE: within effect only; time-invariant variables absorbed by person dummies.","REWB (highlighted): separates both; within ≈ FE; between is new information.","Mundlak: equivalent to REWB; exper_bar = contextual (not between) effect.","For Mundlak: exper_bar column shows contextual effect β_2C, not β_2B." ), notation ="alphabet")
Key coefficients across models. FE cannot estimate time-invariant variables.
Model
exper (within/blend)
exper_bar (between/contextual)
school
black_d
exper
OLS
0.0501
NA
0.1035
-0.1428
1
Fixed Effects
0.0599
NA
NA
NA
exper1
Standard RE
0.0580
NA
0.1081
-0.1412
exper_win
REWB
0.0591
0.0332
0.0946
-0.1340
exper2
Mundlak
0.0591
-0.0259
0.0946
-0.1340
exper_win1
REWB + Random Slopes
0.0590
0.0359
0.0952
-0.1306
a OLS and Std RE: exper coefficient blends within and between effects.
b FE: within effect only; time-invariant variables absorbed by person dummies.
c REWB (highlighted): separates both; within ≈ FE; between is new information.
d Mundlak: equivalent to REWB; exper_bar = contextual (not between) effect.
e For Mundlak: exper_bar column shows contextual effect β_2C, not β_2B.
Key findings:
Within effect (REWB exper_win ≈ FE): each additional year of own experience raises wages by approximately 5.9%. The small difference from FE (0.0599 vs 0.0591) reflects GLS vs OLS estimation, not a modelling difference.
Between effect (REWB exper_bar): workers with one more year of average experience earn 3.3% more. This is materially smaller than the within effect — between-person experience differences are partly confounded with unobserved stable traits (ability, career selection) that also affect wages.
OLS blends both to ~5.0% — an uninterpretable weighted average.
Education (time-invariant): FE cannot estimate this; REWB recovers ~9.5% per year of schooling.
Black ethnicity (time-invariant): FE cannot estimate this; REWB estimates a wage penalty of approximately 13%.
A Cautionary Note: Nonstationarity
WarningAre wages and experience stationary?
Standard FE, RE, and REWB models assume that the variables in the model are stationary (i.e., their statistical properties do not systematically change over time). If wages or key time-varying predictors follow a unit root (stochastic trend), estimates from level-based models can be spurious. This concern is worth investigating before interpreting the results above.
Experience as a deterministic time trend
The most immediate issue is not stochastic at all. In the Cornwell–Rupert data, exper grows by exactly one year per person per year with no exceptions:
Because \(\Delta \text{exper}_{it} = 1\) for every observation, exper is a deterministic linear time trend indexed to when each person entered the labour market. It is perfectly collinear with year within each person.
ImportantWhat the within effect of experience actually identifies
In a within-person (FE or REWB) regression of log wages on experience:
because \(\text{exper}_{it} = \text{exper}_{i,t-1} + 1\) always, the demeaned predictor exper_win is proportional to \((t - \bar{t})\) — a person-centred time index. \(\hat{\beta}_W\) therefore estimates the average annual wage growth rate, not the causal return to one additional year of a worker’s accumulated human capital.
This matters for interpretation. The within estimate (≈ 5.9% per year) conflates genuine returns to experience with any systematic change in real wages over the 1980–1987 period (e.g., business cycle, labour-market shifts). Including year dummies would be a natural control, but since exper increments by exactly 1 each year, year dummies and exper_win are perfectly collinear within persons and cannot both be included.
The between effect of exper_bar is also partly a life-cycle / cohort effect: workers who are older on average in 1980–1987 have more average experience, but may also differ in cohort-specific ways.
Panel unit root tests on wages
Even setting aside the experience issue, log wages themselves may contain a stochastic trend. We apply two panel unit root tests with opposite null hypotheses:
# Im-Pesaran-Shin (2003): H0 = unit root in all panelsips <-purtest(pdat[, "wage"], test ="ips", exo ="intercept", lags =1)# Hadri (2000) KPSS-type: H0 = stationarity in all panelshadri <-purtest(pdat[, "wage"], test ="hadri", exo ="intercept")data.frame(Test =c("Im–Pesaran–Shin (IPS)","Hadri KPSS"),`H₀`=c("All panels have a unit root","All panels are stationary"),Statistic =c(round(ips$statistic$statistic, 3),round(hadri$statistic$statistic, 3)),`p-value`=c(format.pval(ips$statistic$p.value, digits =3),format.pval(hadri$statistic$p.value, digits =3)),Decision =c("Reject H₀ → stationary","Reject H₀ → unit root"),check.names =FALSE) |>kable(caption ="Conflicting panel unit root test results for log wages")
Conflicting panel unit root test results for log wages
Test
H₀
Statistic
p-value
Decision
Wtbar
Im–Pesaran–Shin (IPS)
All panels have a unit root
-25.378
<2e-16
Reject H₀ → stationary
z
Hadri KPSS
All panels are stationary
36.010
<2e-16
Reject H₀ → unit root
The tests give contradictory conclusions — a common finding in short panels:
IPS rejects the unit root null, suggesting stationarity.
Hadri KPSS rejects the stationarity null, suggesting a unit root.
This contradiction is unsurprising given the very short time dimension (T = 8). Both tests have well-known size and power problems in small T settings (Harris & Tzavalis 1999; Hlouskova & Wagner 2006), and with only 8 observations per individual, individual-level ADF tests are uninformative.
# Check whether first-differenced wages are more clearly stationaryips_fd <-purtest(diff(pdat[, "wage"]), test ="ips",exo ="intercept", lags =1)cat(sprintf("IPS on Δwage: statistic = %.3f, p = %.2e\n → %s\n", ips_fd$statistic$statistic, ips_fd$statistic$p.value,if (ips_fd$statistic$p.value <0.05) "Rejects unit root (Δwage stationary)"else"Cannot reject unit root"))
IPS on Δwage: statistic = -63.897, p = 0.00e+00
→ Rejects unit root (Δwage stationary)
First-differenced wages strongly reject the unit root null, consistent with wages being integrated of order one, I(1) — i.e., the level of wages is non-stationary but the change in wages is stationary.
Implications and practical remedies
NoteWhen does nonstationarity matter most?
The concern is most acute for cross-sectional (between) estimates. If wages are I(1) and individual means \(\bar{y}_i\) vary systematically (as they do when T is small and wages have trends), the between-person regression can be spurious. The within estimator is more robust because the within transformation removes a large portion of trending variation, though it does not guarantee consistency under all unit root specifications.
Practical options, in order of preference:
Include year dummies (two-way FE/REWB). Control for any common time trend in wages. However, as noted above, year dummies and exper_win are perfectly collinear within persons in this dataset — so one must be omitted. A reasonable choice is to replace exper with a quadratic in age or a time counter and include year fixed effects.
# Two-way FE: person + year dummies (year_f as factor)d$year_f <-factor(d$year)# REWB with year dummies but WITHOUT exper_win (collinear with year_f within person)m_twoway <-lmer(wage ~ year_f + exper_bar + school + union_d + married_d + health_d + black_d + hisp_d + (1| id),data = d, REML =FALSE)# Show year fixed effects and between effect of experiencefe_coefs <-fixef(m_twoway)cat("Year effects (relative to 1980):\n")
cat(sprintf("\nBetween effect of experience (exper_bar): %.4f\n", fe_coefs["exper_bar"]))
Between effect of experience (exper_bar): 0.0333
/* Two-way FE: absorb person and year effects *//* exper_win omitted -- collinear with year dummies within id */quietlytabulateyear, gen(yr) /* year dummies */mixed wage yr2-yr8 exper_bar school /// union_d married_d health_d black_d hisp_d || id:, reml/* Or equivalently: xtreg wage yr2-yr8 exper_bar ..., re */
First-difference the outcome. Regress \(\Delta \text{wage}_{it}\) on time-varying changes. Since \(\Delta \text{exper} = 1\) always, experience is absorbed into the intercept (average wage growth). This is principled but loses the ability to estimate level effects.
cat("\nIntercept = average annual wage growth rate: ",round(coef(m_fd)["(Intercept)"], 4), "\n")
Intercept = average annual wage growth rate: 0.0648
cat("(experience absorbed into intercept since Δexper = 1 always)\n")
(experience absorbed into intercept since Δexper = 1 always)
/* First-difference estimator *//* exper drops out since Δexper = 1 (absorbed by _cons) */xtset id yeargen d_wage = D.wagegen d_union = D.union_dgen d_married = D.married_dgen d_health = D.health_dregress d_wage d_union d_married d_health/* Intercept = average annual log-wage growth rate */
Test for cointegration. If wages and predictors are all I(1) but cointegrated, the level-based REWB model remains valid as an error-correction representation. Pedroni (1999) panel cointegration tests are available in R via the cointReg package and in Stata via xtpedroni.
Interpret cautiously. With T = 8, the evidence on stationarity is genuinely ambiguous. The most defensible position is to report the REWB estimates in levels alongside the two-way FE and first-difference specifications as robustness checks, and note that the within-person estimate of experience captures average annual wage growth rather than the structural return to human capital accumulation.
Summary of the nonstationarity issue
Concern
Mechanism
Practical effect
exper is a deterministic time trend
\(\Delta\text{exper} = 1\) always
Within effect ≡ average annual wage growth; collinear with year dummies
Wages may be I(1)
Stochastic trend in log wages
Level-based regressions potentially spurious
Short T (= 8)
Low power of unit root tests
Cannot reliably distinguish I(0) from I(1)
Conflicting test results
IPS rejects unit root; Hadri rejects stationarity
Model specification uncertainty
Bottom line: the REWB results are informative and internally consistent, but the within-person estimate of the experience effect should be interpreted as an average annual wage growth rate rather than a pure return to experience. Year fixed effects (in place of exper_win) are a straightforward robustness check when the goal is to separate individual wage growth from common macroeconomic trends.
References
Bell, A., Fairbrother, M. & Jones, K. (2019). Fixed and random effects models: making an informed choice. Quality & Quantity, 53, 1051–1074. https://doi.org/10.1007/s11135-018-0802-x
Bell, A. & Jones, K. (2015). Explaining fixed effects: random effects modelling of time-series cross-sectional and panel data. Political Science Research and Methods, 3(1), 133–153. Replication files: https://doi.org/10.7910/DVN/23415
Cornwell, C. & Rupert, P. (1988). Efficient estimation with panel data: an empirical comparison of instrumental variables estimators. Journal of Applied Econometrics, 3, 149–155.
Hadri, K. (2000). Testing for stationarity in heterogeneous panel data. Econometrics Journal, 3(2), 148–161.
Im, K. S., Pesaran, M. H. & Shin, Y. (2003). Testing for unit roots in heterogeneous panels. Journal of Econometrics, 115(1), 53–74.
Jordan, S. & Philips, A. Q. (2023). Improving the interpretation of random effects regression results. Political Studies Review, 21(1), 210–220. Code: https://github.com/andyphilips/qdmean
Mundlak, Y. (1978). Pooling of time-series and cross-section data. Econometrica, 46(1), 69–85.
Vella, F. & Verbeek, M. (1998). Whose wages do unions raise? A dynamic model of unionism and wage rate determination for young men. Journal of Applied Econometrics, 13(2), 163–183.