UCLA Academic Technology Services HomeServicesClassesContactJobs

Stata FAQ
How can I explain a continuous by continuous interaction? (Stata 11)

An earlier version of this web page showed how to explain continuous by continuous interactions using methods available in Stata 10 and earlier. These methods continue to work in Stata 11. However, Stata 11 has some new features that will allow that can make the task a bit easier.

First off, let's start with what a significant continuous by continuous interaction means. It means that the slope of one continuous variable on the response variable changes as the values on a second continuous change.

Multiple regression models often contain interaction terms. This FAQ page covers the situation in which there is a moderator variable which influences the regression of the dependent variable on an independent/predictor variable. In other words, a regression model that has a significant two-way interaction of continuous variables.

There are several approaches that one might use to explain an interaction of two continuous variables. The approach that we will demonstrate is to compute simple slopes, i.e., the slopes of the dependent variable on the independent variable when the moderator variable is held constant at different combinations of values from very low to very high.

We will consider a regression model which includes a continuous by continuous interaction of a predictor variable with a moderator variable. In the formula, Y is the response variable, X the predictor (independent) variable with Z being the moderator variable. The term XZ is the interaction of the predictor with the moderator.

Y = b0 + b1X + b2Z + b3XZ
We will illustrate the simple slopes process using the hsbdemo dataset that has a statistically significant continuous by continuous interaction. In order to keep the notation consistent we will temporarily change the names of the variables; y for the response variable, x for the independent variable and z for the moderator. As shown in the code below that read is the response variable, math is the predictor and socst is the moderator variable.

Then, after creating the interaction term, we will run the regression model.

use http://www.ats.ucla.edu/stat/data/hsbdemo, clear

rename read y
rename math x
rename socst z

/* get the high and low values for x */
sum x
global max = r(max)
global min = r(min)

regress y c.x##c.z

      Source |       SS       df       MS              Number of obs =     200
-------------+------------------------------           F(  3,   196) =   78.61
       Model |  11424.7622     3  3808.25406           Prob > F      =  0.0000
    Residual |  9494.65783   196  48.4421318           R-squared     =  0.5461
-------------+------------------------------           Adj R-squared =  0.5392
       Total |    20919.42   199  105.122714           Root MSE      =    6.96

------------------------------------------------------------------------------
           y |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
           x |  -.1105123   .2916338    -0.38   0.705    -.6856552    .4646307
           z |  -.2200442   .2717539    -0.81   0.419    -.7559812    .3158928
             |
     c.x#c.z |   .0112807   .0052294     2.16   0.032     .0009677    .0215938
             |
       _cons |   37.84271   14.54521     2.60   0.010     9.157506    66.52792
------------------------------------------------------------------------------
Please note that the interaction, c.x#c.z, is statistically significant with a p-value of 0.032.

Next, we compute the slope for y on x while holding the value of the moderator variable, z, constant at values running from 30 to 75. To do this we will use the margins command with a range of values for z.

margins, dydx(x) at(z=(30(5)75)) vsquish

Average marginal effects                          Number of obs   =        200
Model VCE    : OLS

Expression   : Linear prediction, predict()
dy/dx w.r.t. : x
1._at        : z               =          30
2._at        : z               =          35
3._at        : z               =          40
4._at        : z               =          45
5._at        : z               =          50
6._at        : z               =          55
7._at        : z               =          60
8._at        : z               =          65
9._at        : z               =          70
10._at       : z               =          75

------------------------------------------------------------------------------
             |            Delta-method
             |      dy/dx   Std. Err.      z    P>|z|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
x            |
         _at |
          1  |   .2279094   .1424924     1.60   0.110    -.0513706    .5071894
          2  |    .284313   .1195771     2.38   0.017     .0499463    .5186797
          3  |   .3407166   .0982883     3.47   0.001     .1480752     .533358
          4  |   .3971202   .0799363     4.97   0.000      .240448    .5537924
          5  |   .4535238   .0669803     6.77   0.000      .322245    .5848027
          6  |   .5099274   .0628508     8.11   0.000     .3867422    .6331127
          7  |   .5663311   .0691477     8.19   0.000     .4308041     .701858
          8  |   .6227347   .0835458     7.45   0.000     .4589878    .7864815
          9  |   .6791383   .1026924     6.61   0.000     .4778649    .8804117
         10  |   .7355419   .1244141     5.91   0.000     .4916947    .9793891
------------------------------------------------------------------------------
The values in the margins command gives the amount of change in y with a one unit change in x while holding z constant at different values, i.e., the values are simple slopes. The margins command stores the simple slopes in a vector r(b). We will make a copy of that vector, call it s, and use the values to graph the simple slopes on top of a scatter plot of y and x.
mat s=r(b)

mat list s

s[1,10]
            x:         x:         x:         x:         x:         x:         x:         x:         x:         x:
            1.         2.         3.         4.         5.         6.         7.         8.         9.        10.
          _at        _at        _at        _at        _at        _at        _at        _at        _at        _at
r1  .22790939    .284313  .34071661  .39712022  .45352383  .50992744  .56633105  .62273466  .67913827  .73554189
Next, we need to compute the intercepts. The intercepts for each of the simple regression lines are the values of the response variable when x is equal to zero. We will use the margins commamd again with several additional options. Once computed we will save the values of the intercepts in a matrix named i.
margins, at(x=0 z=(30(5)75)) asbalanced noesample noestimcheck force vsquish

Adjusted predictions                              Number of obs   =        200
Model VCE    : OLS

Expression   : Linear prediction, predict()
1._at        : x               =           0
               z               =          30
2._at        : x               =           0
               z               =          35
3._at        : x               =           0
               z               =          40
4._at        : x               =           0
               z               =          45
5._at        : x               =           0
               z               =          50
6._at        : x               =           0
               z               =          55
7._at        : x               =           0
               z               =          60
8._at        : x               =           0
               z               =          65
9._at        : x               =           0
               z               =          70
10._at       : x               =           0
               z               =          75

------------------------------------------------------------------------------
             |            Delta-method
             |     Margin   Std. Err.      z    P>|z|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
         _at |
          1  |   31.24139   6.873932     4.54   0.000     17.76873    44.71405
          2  |   30.14117   5.726198     5.26   0.000     18.91803    41.36431
          3  |   29.04095   4.692576     6.19   0.000     19.84367    38.23823
          4  |   27.94073   3.865708     7.23   0.000     20.36408    35.51737
          5  |   26.84051   3.399947     7.89   0.000     20.17673    33.50428
          6  |   25.74028   3.445008     7.47   0.000     18.98819    32.49238
          7  |   24.64006   3.983596     6.19   0.000     16.83236    32.44777
          8  |   23.53984   4.854122     4.85   0.000     14.02594    33.05375
          9  |   22.43962   5.911723     3.80   0.000     10.85286    34.02639
         10  |    21.3394   7.072973     3.02   0.003     7.476628    35.20217
------------------------------------------------------------------------------

mat i=r(b)

mat list i

i[1,10]
            1.         2.         3.         4.         5.         6.         7.         8.         9.        10.
          _at        _at        _at        _at        _at        _at        _at        _at        _at        _at
r1  31.241389  30.141168  29.040947  27.940726  26.840505  25.740284  24.640063  23.539842  22.439622  21.339401
Now, with the intercepts in matrix i and the slopes in s we can go ahead and plot the simple slopes.
twoway (function y = i[1,1] + s[1,1]*x, range($min $max))  ///
       (function y = i[1,2] + s[1,2]*x, range($min $max))  ///
       (function y = i[1,3] + s[1,3]*x, range($min $max))  ///
       (function y = i[1,4] + s[1,4]*x, range($min $max))  ///
       (function y = i[1,5] + s[1,5]*x, range($min $max))  ///
       (function y = i[1,6] + s[1,6]*x, range($min $max))  ///
       (function y = i[1,7] + s[1,7]*x, range($min $max))  ///
       (function y = i[1,8] + s[1,8]*x, range($min $max))  ///
       (function y = i[1,9] + s[1,9]*x, range($min $max))  ///
       (function y = i[1,10] + s[1,10]*x, range($min $max)) ///
       (scatter y x, msym(oh) jitter(3)),                   ///
       legend(off) ytitle(Y) xtitle(X) scheme(lean1)
       
In the above graph the bottom line is the simple slope when z equals 30 and the top line is when z equals 75. So it is easy to see that the simple slope increases as z increases.

What if you have additional variables in your model? Its not a problem as long as the other variables don't interact with either x or z. The values of the simple slopes will change but because this is a linear model it doesn't matter what values you hold the other variables at. The easiest way is just to hold the other variables at their mean values with the atmeans option in margins. Here is an example adding write to our model.

regress y c.x##c.z write

      Source |       SS       df       MS              Number of obs =     200
-------------+------------------------------           F(  4,   195) =   62.69
       Model |   11768.436     4    2942.109           Prob > F      =  0.0000
    Residual |  9150.98401   195  46.9281231           R-squared     =  0.5626
-------------+------------------------------           Adj R-squared =  0.5536
       Total |    20919.42   199  105.122714           Root MSE      =  6.8504

------------------------------------------------------------------------------
           y |      Coef.   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
           x |  -.2285181   .2903336    -0.79   0.432    -.8011152    .3440789
           z |  -.3206324   .2700438    -1.19   0.237    -.8532139     .211949
             |
     c.x#c.z |   .0119774   .0051534     2.32   0.021     .0018138     .022141
             |
       write |    .193212   .0713966     2.71   0.007     .0524034    .3340206
       _cons |   37.16971   14.31827     2.60   0.010     8.931167    65.40826
------------------------------------------------------------------------------

/* hold write at 20 */

margins , dydx(x) at(z=(30(5)75) write=20) vsquish

Average marginal effects                          Number of obs   =        200
Model VCE    : OLS

Expression   : Linear prediction, predict()
dy/dx w.r.t. : x
1._at        : z               =          30
               write           =          20
2._at        : z               =          35
               write           =          20
3._at        : z               =          40
               write           =          20
4._at        : z               =          45
               write           =          20
5._at        : z               =          50
               write           =          20
6._at        : z               =          55
               write           =          20
7._at        : z               =          60
               write           =          20
8._at        : z               =          65
               write           =          20
9._at        : z               =          70
               write           =          20
10._at       : z               =          75
               write           =          20

------------------------------------------------------------------------------
             |            Delta-method
             |      dy/dx   Std. Err.      z    P>|z|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
x            |
         _at |
          1  |   .1308037   .1447656     0.90   0.366    -.1529317    .4145391
          2  |   .1906907   .1226729     1.55   0.120    -.0497438    .4311252
          3  |   .2505777   .1023138     2.45   0.014     .0500464     .451109
          4  |   .3104646   .0849439     3.65   0.000     .1439776    .4769517
          5  |   .3703516   .0727374     5.09   0.000      .227789    .5129143
          6  |   .4302386   .0685119     6.28   0.000     .2959577    .5645195
          7  |   .4901256   .0736542     6.65   0.000      .345766    .6344851
          8  |   .5500125   .0865095     6.36   0.000      .380457    .7195681
          9  |   .6098995   .1042629     5.85   0.000      .405548     .814251
         10  |   .6697865   .1248419     5.37   0.000     .4251009    .9144721
------------------------------------------------------------------------------

/* hold write at its mean value */

margins , dydx(x) at(z=(30(5)75)) atmeans vsquish

Conditional marginal effects                      Number of obs   =        200
Model VCE    : OLS

Expression   : Linear prediction, predict()
dy/dx w.r.t. : x

1._at        : x               =      52.645 (mean)
               z               =          30
               write           =      52.775 (mean)
2._at        : x               =      52.645 (mean)
               z               =          35
               write           =      52.775 (mean)
3._at        : x               =      52.645 (mean)
               z               =          40
               write           =      52.775 (mean)
4._at        : x               =      52.645 (mean)
               z               =          45
               write           =      52.775 (mean)
5._at        : x               =      52.645 (mean)
               z               =          50
               write           =      52.775 (mean)
6._at        : x               =      52.645 (mean)
               z               =          55
               write           =      52.775 (mean)
7._at        : x               =      52.645 (mean)
               z               =          60
               write           =      52.775 (mean)
8._at        : x               =      52.645 (mean)
               z               =          65
               write           =      52.775 (mean)
9._at        : x               =      52.645 (mean)
               z               =          70
               write           =      52.775 (mean)
10._at       : x               =      52.645 (mean)
               z               =          75
               write           =      52.775 (mean)

------------------------------------------------------------------------------
             |            Delta-method
             |      dy/dx   Std. Err.      z    P>|z|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
x            |
         _at |
          1  |   .1308037   .1447656     0.90   0.366    -.1529317    .4145391
          2  |   .1906907   .1226729     1.55   0.120    -.0497438    .4311252
          3  |   .2505777   .1023138     2.45   0.014     .0500464     .451109
          4  |   .3104646   .0849439     3.65   0.000     .1439776    .4769517
          5  |   .3703516   .0727374     5.09   0.000      .227789    .5129143
          6  |   .4302386   .0685119     6.28   0.000     .2959577    .5645195
          7  |   .4901256   .0736542     6.65   0.000      .345766    .6344851
          8  |   .5500125   .0865095     6.36   0.000      .380457    .7195681
          9  |   .6098995   .1042629     5.85   0.000      .405548     .814251
         10  |   .6697865   .1248419     5.37   0.000     .4251009    .9144721
------------------------------------------------------------------------------
You will note that the simple slopes are the same in the two margins commands above even though we have write constant at 20 in the first on and at 52.775 in the second one.

How to cite this page

Report an error on this page

UCLA Researchers are invited to our Statistical Consulting Services
We recommend others to our list of Other Resources for Statistical Computing Help
These pages are Copyrighted (c) by UCLA Academic Technology Services


The content of this web site should not be construed as an endorsement of any particular web site, book, or software product by the University of California.