Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Panel data analysis with fixed and random effects models
.claude/skills/brycewang-stanford-panel-data-guide/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-08 | ✗→✓ | ▲ Improved | 125% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 81% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 144% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 203% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 307% | 0% |
Estimate and interpret fixed effects, random effects, and dynamic panel models using Stata, R, and Python for longitudinal/panel datasets.
Panel data (also called longitudinal or cross-sectional time-series data) tracks the same units (individuals, firms, countries) across multiple time periods. This structure enables:
| unit_id | year | gdp_growth | investment | trade_openness |
|---------|------|-----------|------------|----------------|
| USA | 2015 | 2.9 | 20.5 | 28.3 |
| USA | 2016 | 1.7 | 20.1 | 27.1 |
| USA | 2017 | 2.3 | 20.8 | 27.5 |
| CHN | 2015 | 6.9 | 43.3 | 39.9 |
| CHN | 2016 | 6.7 | 42.7 | 37.2 |
| CHN | 2017 | 6.9 | 43.1 | 38.1 |Key notation:
Y_it = alpha + beta * X_it + epsilon_itIgnores panel structure; assumes no unit-specific effects. Rarely appropriate.
Y_it = alpha_i + beta * X_it + epsilon_itEach unit has its own intercept (alpha_i) that captures all time-invariant unobserved heterogeneity. The "within" estimator removes alpha_i by demeaning.
Y_it = alpha + beta * X_it + u_i + epsilon_itThe unit-specific effect u_i is treated as random and uncorrelated with X_it.
stata* Declare panel structure xtset country_id year * Summarize within and between variation xtsum gdp_growth investment trade_openness
stata* Fixed effects regression xtreg gdp_growth investment trade_openness, fe * Store results for Hausman test estimates store FE * Fixed effects with robust standard errors (clustered by unit) xtreg gdp_growth investment trade_openness, fe vce(cluster country_id) * Test joint significance of fixed effects testparm i.country_id
stata* Random effects regression xtreg gdp_growth investment trade_openness, re * Store results for Hausman test estimates store RE
stata* Hausman specification test hausman FE RE * If p < 0.05: reject RE, use FE * If p > 0.05: RE is consistent and efficient, prefer RE
stata* First-differenced regression (alternative to FE) reg D.gdp_growth D.investment D.trade_openness, vce(cluster country_id)
rlibrary(plm) # Convert to panel data frame pdata <- pdata.frame(mydata, index = c("country_id", "year")) # Fixed effects fe_model <- plm(gdp_growth ~ investment + trade_openness, data = pdata, model = "within") summary(fe_model) # Random effects re_model <- plm(gdp_growth ~ investment + trade_openness, data = pdata, model = "random") summary(re_model) # Hausman test phtest(fe_model, re_model) # Clustered standard errors library(lmtest) library(sandwich) coeftest(fe_model, vcov = vcovHC(fe_model, type = "HC1", cluster = "group")) # Time fixed effects fe_twoway <- plm(gdp_growth ~ investment + trade_openness + factor(year), data = pdata, model = "within") # Test for time fixed effects pFtest(fe_twoway, fe_model)
pythonimport pandas as pd from linearmodels.panel import PanelOLS, RandomEffects, compare # Set multi-index for panel structure data = data.set_index(["country_id", "year"]) # Fixed effects fe = PanelOLS.from_formula( "gdp_growth ~ investment + trade_openness + EntityEffects", data=data ) fe_result = fe.fit(cov_type="clustered", cluster_entity=True) print(fe_result.summary) # Random effects re = RandomEffects.from_formula( "gdp_growth ~ investment + trade_openness + 1", data=data ) re_result = re.fit() print(re_result.summary) # Two-way fixed effects (entity + time) twoway = PanelOLS.from_formula( "gdp_growth ~ investment + trade_openness + EntityEffects + TimeEffects", data=data ) twoway_result = twoway.fit(cov_type="clustered", cluster_entity=True) print(twoway_result.summary) # Compare models print(compare({"FE": fe_result, "RE": re_result, "Two-way FE": twoway_result}))
| Test | Stata | R | Null Hypothesis | |------|-------|---|----------------| | F-test for FE | Built into xtreg, fe | pFtest() | All alpha_i = 0 (pooled OLS is appropriate) | | Breusch-Pagan LM | xttest0 | plmtest() | Var(u_i) = 0 (pooled OLS vs. RE) | | Hausman | hausman FE RE | phtest() | RE is consistent (u_i uncorrelated with X) |
stata* Wooldridge test for serial correlation in panel data xtserial gdp_growth investment trade_openness * If p < 0.05: serial correlation present; use clustered SE or AR(1) correction
r# Wooldridge test pbgtest(fe_model) # Breusch-Godfrey test for serial correlation
stata* Modified Wald test for groupwise heteroskedasticity xttest3 * If p < 0.05: heteroskedasticity present; use robust/clustered SE
When a lagged dependent variable is included as a regressor:
stata* Arellano-Bond one-step GMM xtabond gdp_growth investment trade_openness, lags(1) vce(robust) * System GMM (Blundell-Bond) - more efficient xtdpdsys gdp_growth investment trade_openness, lags(1) vce(robust) * Sargan/Hansen test for overidentifying restrictions * AR(2) test for second-order serial correlation
stata* Basic DID with two-way fixed effects xtreg outcome treated##post, fe vce(cluster unit_id) * Event study specification xtreg outcome i.relative_time##treated, fe vce(cluster unit_id)
Table X: Panel Regression Results (Fixed Effects)
Dependent Variable: GDP Growth (%)
(1) (2) (3)
FE RE Two-way FE
Investment 0.125*** 0.118*** 0.131***
(0.032) (0.029) (0.035)
Trade Openness 0.045** 0.051** 0.038*
(0.018) (0.017) (0.020)
Entity FE Yes No Yes
Time FE No No Yes
Observations 850 850 850
R-squared (within) 0.234 0.228 0.267
Hausman test (p) -- 0.003 --
Notes: Robust standard errors clustered at the country level in
parentheses. * p<0.10, ** p<0.05, *** p<0.01.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 6,483 | 7,344 | +13% | 1 | 1 | 0% | 1,124 | 3,410 | +203% | 0 | 0 | — |
case-02 | pass→pass | 4,195 | 5,454 | +30% | 1 | 1 | 0% | 766 | 3,121 | +307% | 0 | 0 | — |
case-03 | pass→pass | 9,711 | 10,862 | +12% | 1 | 1 | 0% | 1,831 | 4,193 | +129% | 0 | 0 | — |
case-04 | pass→pass | 6,337 | 4,385 | -31% | 1 | 1 | 0% | 1,104 | 2,956 | +168% | 0 | 0 | — |
case-05 | pass→pass | 3,759 | 2,680 | -29% | 1 | 1 | 0% | 770 | 2,717 | +253% | 0 | 0 | — |
case-06 | pass→pass | 6,006 | 3,685 | -39% | 1 | 1 | 0% | 1,202 | 2,826 | +135% | 0 | 0 | — |
case-07 | pass→pass | 10,497 | 6,968 | -34% | 1 | 1 | 0% | 1,920 | 3,573 | +86% | 0 | 0 | — |
case-08 | fail→pass | 8,050 | 6,989 | -13% | 1 | 1 | 0% | 1,589 | 3,574 | +125% | 0 | 0 | — |
case-09 | pass→pass | 8,459 | 6,624 | -22% | 1 | 1 | 0% | 1,621 | 3,437 | +112% | 0 | 0 | — |
case-10 | fail→pass | 9,305 | 5,734 | -38% | 1 | 1 | 0% | 1,793 | 3,241 | +81% | 0 | 0 | — |
case-11 | pass→pass | 9,983 | 7,797 | -22% | 1 | 1 | 0% | 1,899 | 3,644 | +92% | 0 | 0 | — |
case-12 | pass→pass | 5,555 | 4,065 | -27% | 1 | 1 | 0% | 1,063 | 2,917 | +174% | 0 | 0 | — |
case-13 | pass→pass | 5,782 | 5,880 | +2% | 1 | 1 | 0% | 1,083 | 3,264 | +201% | 0 | 0 | — |
case-14 | pass→pass | 2,538 | 3,445 | +36% | 1 | 1 | 0% | 486 | 2,744 | +465% | 0 | 0 | — |
case-15 | pass→pass | 4,563 | 3,170 | -31% | 1 | 1 | 0% | 794 | 2,769 | +249% | 0 | 0 | — |
case-16 | pass→pass | 8,945 | 5,259 | -41% | 1 | 1 | 0% | 1,647 | 2,948 | +79% | 0 | 0 | — |
case-17 | pass→pass | 9,331 | 6,796 | -27% | 1 | 1 | 0% | 1,582 | 3,300 | +109% | 0 | 0 | — |
case-18 | pass→pass | 8,503 | 6,845 | -19% | 1 | 1 | 0% | 1,552 | 3,440 | +122% | 0 | 0 | — |
case-19 | fail→pass | 8,965 | 9,232 | +3% | 1 | 1 | 0% | 1,529 | 3,734 | +144% | 0 | 0 | — |
case-20 | pass→pass | 3,349 | 3,196 | -5% | 1 | 1 | 0% | 536 | 2,774 | +418% | 0 | 0 | — |
case-21 | pass→pass | 18,237 | 18,167 | -0% | 1 | 1 | 0% | 3,086 | 5,288 | +71% | 0 | 0 | — |
case-22 | pass→pass | 8,939 | 7,662 | -14% | 1 | 1 | 0% | 1,503 | 3,497 | +133% | 0 | 0 | — |
case-23 | pass→pass | 15,973 | 17,267 | +8% | 1 | 1 | 0% | 2,949 | 5,456 | +85% | 0 | 0 | — |
case-24 | pass→pass | 23,318 | 28,403 | +22% | 1 | 1 | 0% | 4,184 | 7,529 | +80% | 0 | 0 | — |
case-25 | pass→pass | 11,373 | 11,202 | -2% | 1 | 1 | 0% | 1,973 | 3,997 | +103% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +12 percentage points is the difference between those two pass rates over the 25 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.