Interaction Effects in Stata: Factor Variables, margins, and Interpretation
Interactions trip everyone up. Here's how i.x##i.z and c.x#c.z work, how to use margins and marginsplot to interpret them, and the common mistakes.
You added an interaction term, but now none of the main-effect coefficients mean what you expected.
You will estimate, interpret, and visualize interactions correctly without manual algebra mistakes.
All examples tested in Stata 18 SE. Compatible with Stata 15+.
Quick Answer
- Use factor-variable syntax (`c.var##i.group`) instead of manual interaction variables.
- Interpret conditional effects with margins, not raw coefficients alone.
- Plot effects at meaningful values to communicate moderation clearly.
- Document reference categories explicitly.
Model Moderation with Correct Syntax and Interpretation
Estimate interactions using factor-variable notation
Factor-variable syntax ensures Stata tracks main and interaction terms consistently, reducing specification errors in complex models.
Use clear coding for categorical moderators and keep reference categories explicit in outputs.
If you are extending this pipeline, also review How to Merge Datasets in Stata and How to Structure a Stata Project.
1clear all2set obs 30003gen firm_id = ceil(_n/12)4gen year = 2010 + mod(_n,10)5gen education = 8 + floor(runiform()*10)6gen female = mod(_n,2)7gen experience = 18 + floor(runiform()*20)89gen wage = 11 + 0.7*education + 0.2*experience + 1.1*female + 0.15*(education*female) + rnormal(0,2)1011regress wage c.education##i.female experience i.year, vce(cluster firm_id)------------------------------------------------------------------------------
wage | Coefficient std. err. t P>|t|
-------------+----------------------------------------
education | .6841911 .0281083 24.34 0.000
1.female | 1.052774 .2193401 4.80 0.000
|
female#c.education |
1 | .1479206 .0179045 8.26 0.000
experience | .1963721 .0112334 17.48 0.000
------------------------------------------------------------------------------Compute conditional effects with margins and plot
Raw interaction coefficients are not final answers. margins lets you report effects for each subgroup or covariate value directly.
This step is especially important when presenting results to nontechnical audiences.
1clear all2set obs 30003gen firm_id = ceil(_n/12)4gen year = 2010 + mod(_n,10)5gen education = 8 + floor(runiform()*10)6gen female = mod(_n,2)7gen experience = 18 + floor(runiform()*20)89gen wage = 11 + 0.7*education + 0.2*experience + 1.1*female + 0.15*(education*female) + rnormal(0,2)1011regress wage c.education##i.female experience i.year, vce(cluster firm_id)1213* ---- Section-specific continuation ----14margins female, dydx(education)15marginsplot, recast(line) noci ytitle("Effect of education on wage") xtitle("Female")1617margins, at(education=(10 12 14 16) female=(0 1))Average marginal effects Number of obs = 3,000
Expression: Linear prediction, predict()
dy/dx wrt: education
1._at: female = 0
2._at: female = 1
-------------------------------------------------------------
| dy/dx std. err. z P>|z|
-------------+-----------------------------------------
1._at | .6841911 .0281083 24.34 0.000
2._at | .8321117 .0235179 35.38 0.000
-------------------------------------------------------------Common Errors and Fixes
"variable female#c.education not found"
You attempted to reference an interaction term as a raw variable instead of using factor-variable syntax in the model command.
Use c.education##i.female directly in estimation; Stata will create and track interaction terms internally.
variable female#c.education not found r(111);
regress wage education female female#c.educationregress wage c.education##i.female1regress wage c.education##i.female experience i.year, vce(cluster firm_id)2margins female, dydx(education)Average marginal effects Expression: Linear prediction, predict()
Command Reference
factor variables (i. c. # ##)
Stata docs โCreates main and interaction effects with automatic bookkeeping for postestimation.
i.varCategorical factor variablec.varContinuous variable marker#Interaction only##Main effects plus interactionHow Sytra Handles This
Sytra can convert hypothesis statements about moderation into valid factor-variable syntax and margins interpretation blocks.
A direct natural-language prompt for this exact workflow:
Estimate wage on education with a female interaction using factor-variable syntax, cluster by firm_id, then report conditional education effects by female status with margins and marginsplot.Sytra catches these errors before you run.
Sytra can convert hypothesis statements about moderation into valid factor-variable syntax and margins interpretation blocks.
Join the Waitlist โFAQ
What is the difference between # and ## in Stata?
x#z includes only the interaction term, while x##z includes both main effects and interaction in one expression.
Should I center continuous variables before interactions?
Centering can improve interpretability of main effects, especially when zero is not substantively meaningful.
How do I visualize interaction effects?
Use margins with at() to compute conditional effects and marginsplot to present them clearly.
Related Guides
- Stata margins: Complete Guide to Marginal Effects with Interpretation
- Stata Factor Variables: i., c., ibn., and # Notation Explained
- Logistic Regression in Stata: Marginal Effects That Actually Make Sense
- Difference-in-Differences in Stata: A Complete Guide
- Explore the regression pillar page
- Open the full regression guide index
- Browse all Stata & R guides on the blog index
- Browse all Stata pillars
We build practical, reproducible workflows for Stata and R teams working on real empirical research pipelines.