Regression
2026-02-2512 min read

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.

Sytra Team
Research Engineering Team, Sytra AI

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

  1. Use factor-variable syntax (`c.var##i.group`) instead of manual interaction variables.
  2. Interpret conditional effects with margins, not raw coefficients alone.
  3. Plot effects at meaningful values to communicate moderation clearly.
  4. 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.

interaction-model.do
stata
1clear all
2set obs 3000
3gen 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)
8
9gen wage = 11 + 0.7*education + 0.2*experience + 1.1*female + 0.15*(education*female) + rnormal(0,2)
10
11regress wage c.education##i.female experience i.year, vce(cluster firm_id)
. regress 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
------------------------------------------------------------------------------
๐Ÿ’กPrefer ## for full specification
Using `##` keeps main effects and interaction aligned, reducing omitted-term mistakes when model specs evolve.

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.

interaction-margins.do
stata
1clear all
2set obs 3000
3gen 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)
8
9gen wage = 11 + 0.7*education + 0.2*experience + 1.1*female + 0.15*(education*female) + rnormal(0,2)
10
11regress wage c.education##i.female experience i.year, vce(cluster firm_id)
12
13* ---- Section-specific continuation ----
14margins female, dydx(education)
15marginsplot, recast(line) noci ytitle("Effect of education on wage") xtitle("Female")
16
17margins, at(education=(10 12 14 16) female=(0 1))
. margins female, dydx(education)
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
-------------------------------------------------------------
๐Ÿ‘Do not hand-calculate subgroup effects in spreadsheets
Manual post-processing is error-prone. margins computes exact linear combinations with correct variance propagation.

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.

. regress wage education female female#c.education
variable female#c.education not found
r(111);
This causes the error
wrong-way.do
stata
regress wage education female female#c.education
This is the fix
right-way.do
stata
regress wage c.education##i.female
error-fix.do
stata
1regress wage c.education##i.female experience i.year, vce(cluster firm_id)
2margins female, dydx(education)
. margins 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.

regress y c.x##i.z controls
i.varCategorical factor variable
c.varContinuous variable marker
#Interaction only
##Main effects plus interaction

How 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:

sytra-prompt.txt
bash
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.


Written by Sytra Team
Research Engineering Team, Sytra AI

We build practical, reproducible workflows for Stata and R teams working on real empirical research pipelines.

#Stata#Interactions#Factor Variables#Econometrics

Enjoyed this article?