## 5.9 Interactions

In the MLR models we have encountered so far, each regression coefficient is interpreted as the effect of a predictor while holding other predictors at fixed values and the effect does not depend on at which specific values you hold the other predictors. How do we model a scenario in which the effect *does* depend on the level of one of the other variables? This is accomplished by including an **interaction** in the model, which treats the other variable as a moderator (effect modifier) (Section 5.8). An interaction between two predictors is referred to as a **two-way interaction**. It is possible to have three-way (or more way) interactions, but this section will only discuss two-way interactions.

### 5.9.1 Understanding a two-way interaction using stratification

Effect modification and the use of interactions tend to be challenging for many students of regression when first encountered. Rather than diving straight into the details of including an interaction in a regression model, we start by clarifying what an interaction is through the use of stratification. As described at the end of Section 5.8.3, including an interaction is similar to stratifying the analysis by another variable and estimating the effect of a variable within levels of another.

**Example 5.2:** In the regression of fasting glucose on waist circumference, does the effect of waist circumference on fasting glucose depend on gender? Stratify by gender, fit a regression model for each gender, and compare the waist circumference effects between the two models. Are they the same or different? If they are different, then gender is an effect modifier (it modifies the waist circumference association with fasting glucose).

```
# Stratify by gender
<- nhanesf.complete %>%
nhanesf.complete.M filter(RIAGENDR == "Male")
<- nhanesf.complete %>%
nhanesf.complete.F filter(RIAGENDR == "Female")
```

Run the following to verify that the code results in datasets of the correct size.

```
# Check
table(nhanesf.complete$RIAGENDR, exclude = NULL)
nrow(nhanesf.complete.M)
nrow(nhanesf.complete.F)
```

```
# Fit for Males
2.strat.M <- lm(LBDGLUSI ~ BMXWAIST, data = nhanesf.complete.M)
fit.ex5.# Fit for Females
2.strat.F <- lm(LBDGLUSI ~ BMXWAIST, data = nhanesf.complete.F)
fit.ex5.
# Fit ignoring gender (for comparison)
# (fit earlier)
# fit.ex4.1.cc <- lm(LBDGLUSI ~ BMXWAIST, data = nhanesf.complete)
coef(fit.ex4.1.cc)["BMXWAIST"]
```

```
## BMXWAIST
## 0.02883
```

```
# Males only
coef(fit.ex5.2.strat.M)["BMXWAIST"]
```

```
## BMXWAIST
## 0.04024
```

```
# Females only
coef(fit.ex5.2.strat.F)["BMXWAIST"]
```

```
## BMXWAIST
## 0.01988
```

The crude (unadjusted) regression coefficient for waist circumference was 0.029, however this effect differs between males (0.040) and females (0.020).

An obvious question is “How different do stratum-specific effects have to be before concluding there is meaningful effect modification?” There is no absolute answer to this question. In the next sections you will learn how to test if the effects significantly differ between strata. However, as with all hypothesis tests, this only clarifies statistical significance, not practical significance. Therefore, we will also use visualizations to help assess if the magnitude of effect modification is meaningful.

### 5.9.2 Including an interaction in a regression model

While one *could* use stratification to handle effect modification, typically it is done by including in the model both the effect modifier and the **interaction** between the effect modifier and the predictor of interest. Advantages of this method include the ability to test the significance of an interaction (are the effects significantly different between strata?) and to estimate the effect of the effect modifier on the outcome, neither of which is possible using stratification.

When including an interaction between two predictors in a model, include each of the predictors individually (the **main effects**) as well as their interaction. The syntax in R is `lm(Y ~ X + Z + X:Z)`

where `X:Z`

is the interaction term. Unless the value of 0 is meaningful, it is helpful to center any continuous predictor that is part of an interaction, as that will make the intercept and main effects more interpretable. Centering is not required, however, and does not change the fit of the model.

**NOTES:**

- Interaction is not the same as correlation. Correlation has to do with how two variables are related to each other whereas interaction has to do with how each of two variables impacts the effect of the other on the outcome.
- When there are just two predictors – the predictor of interest and a categorical effect modifier – stratification and interaction will lead to the same stratum-specific effect estimates for the predictor of interest. When there are additional predictors in the model, this may not be the case. Stratification is equivalent to interacting the effect modifier with
*every*other predictor in the model whereas including an interaction only interacts the effect modifier with the predictor of interest. Even without additional predictors, stratification and interaction will not lead to exactly the same confidence intervals and p-values since the interaction model assumes the error variance is the same across all strata while the stratified model does not.

**Example 5.2 (continued):** In the regression of fasting glucose on waist circumference, does the effect of waist circumference on fasting glucose depend on gender? Use an interaction to answer this question. For comparison, first fit a model that includes waist circumference and gender as a confounder, then fit a model that includes both main effects and a waist circumference \(\times\) gender interaction. Center waist circumference at 100 cm before fitting the models as that will aid in interpreting the intercept and main effects.

```
# Center BMXWAIST at 100
<- nhanesf.complete %>%
nhanesf.complete mutate(cBMXWAIST = BMXWAIST - 100)
# Fit with no interaction (for comparison)
2.noint <- lm(LBDGLUSI ~ cBMXWAIST + RIAGENDR,
fit.ex5.data = nhanesf.complete)
# Fit with interaction
2.int <- lm(LBDGLUSI ~ cBMXWAIST + RIAGENDR +
fit.ex5.:RIAGENDR,
cBMXWAISTdata = nhanesf.complete)
```

### 5.9.3 Regression equation with no interaction

Before explaining the output from the model with an interaction, let’s review the interpretation of the output of the model without an interaction. The model with no interaction is written as

\[ \textrm{FG} = \beta_0 + \beta_1 (\textrm{WC} - 100) + \beta_2 I(\textrm{Gender} = \textrm{Female}) + \epsilon \]

and has the following (rounded) estimated regression coefficients.

`round(summary(fit.ex5.2.noint)$coef, 3)`

```
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.258 0.080 78.428 0.000
## cBMXWAIST 0.028 0.003 9.018 0.000
## RIAGENDRFemale -0.314 0.108 -2.910 0.004
```

From the output above, we see that the equation for the estimated mean is:

\[ E(\textrm{FG} | \textrm{WC}, \textrm{Gender}) = 6.258 + 0.028 \times (\textrm{WC} - 100) - 0.314 \times I(Gender = Female) \]

The interpretation of these coefficients is as follows:

**Intercept:**The intercept is the mean outcome when all predictors are 0 or at their reference level. In this example, (WC - 100) = 0 when WC = 100 and I(Gender = Female) = 0 when Gender = Male (the reference level for gender). Thus, the intercept (6.258 mmol/L) is the mean fasting glucose among males with a waist circumference of 100 cm. One reason we centered WC at 100 cm is so the intercept would represent a plausible outcome value, at WC = 100 cm rather than the impossible value of 0 cm.**Coefficient for WC:**For a given gender, a 1 cm difference in WC is associated with a 0.028 mmol/L difference in fasting glucose. This model*assumes*this effect is the same for males and females. The model in the next section, with an interaction, will relax this assumption.**Coefficient for Gender:**Females have an average fasting glucose that is -0.314 mmol/L lower (since the coefficient is negative) than males with the same WC. This model*assumes*this gender difference is the same at all WC values. The model in the next section, with an interaction, will relax this assumption.

### 5.9.4 Regression equation with an interaction

The model with an interaction is written as

\[ \textrm{FG} = \beta_0 + \beta_1 (\textrm{WC} - 100) + \beta_2 I(\textrm{Gender} = \textrm{Female}) + \beta_3 (WC - 100) I(Gender = Female) + \epsilon \]

and has the following (rounded) estimated regression coefficients.

`round(summary(fit.ex5.2.int)$coef, 3)`

```
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.233 0.080 78.169 0.000
## cBMXWAIST 0.040 0.005 8.276 0.000
## RIAGENDRFemale -0.290 0.107 -2.704 0.007
## cBMXWAIST:RIAGENDRFemale -0.020 0.006 -3.218 0.001
```

Equation (5.2) is the equation for the estimated mean.

\[\begin{equation} \begin{array}{rcl} E(\textrm{FG} | \textrm{WC}, \textrm{Gender}) & = & 6.233 \\ & + & 0.040 \times (\textrm{WC} - 100) \\ & - & 0.290 \times I(\textrm{Gender} = \textrm{Female}) \\ & - & 0.020 \times (\textrm{WC} - 100) \times I(\textrm{Gender} = \textrm{Female}) \end{array} \tag{5.2} \end{equation}\]

The interpretation of these coefficients is as follows.

**Intercept:**The mean fasting glucose among males with WC = 100 cm is 6.233 mmol/L.**Coefficient for WC (“WC main effect”):***Among males*(the value at which the other term in the interaction is 0 or at its reference level), a 1 cm difference in WC is associated with a 0.040 mmol/L difference in fasting glucose.**Coefficient for Gender (“Gender main effect”):***Among those with WC = 100*(the value at which the other term in the interaction is 0 or at its reference level), females have an average fasting glucose that is 0.290 mmol/L lower (since the coefficient is negative) than males.**Coefficient for WC × Gender (“interaction effect”):**This model allows the effect of each predictor in the interaction to differ depending on the level of the other. The interaction effect describes the rate at which that occurs. The interaction has two interpretations. First, the WC effect on fasting glucose is -0.020 different for females than for males. Second, the gender difference in mean fasting glucose changes by -0.020 mmol/L for each 1 cm difference in WC.

**NOTE:** When there is an interaction in the model, be very careful when interpreting the main effects – they are NOT the overall effects of each predictor since each predictor involved in an interaction does not have a single overall effect (see Section 5.9.11 for how to get an appropriate overall test for a predictor involved in an interaction). **A main effect is the effect of a predictor when the other predictor in the interaction is 0 or at its reference level.** The answer to “What is the effect of WC on fasting glucose?” is “it depends on gender” (and vice versa). There is no single main effect for WC or for gender – each depends on the other.

#### 5.9.4.1 Examining the equation for each gender

Break down the regression equation by gender to see how exactly the WC effect differs between males and females. With just two predictors, one of which is categorical, this is exactly the same as stratifying (Section 5.9.1) (at least for the coefficient estimates).

To get the regression equation for males, plug \(\textrm{Gender} = \textrm{Male}\) into Equation (5.2). Doing so results in \(I(\textrm{Gender} = \textrm{Female}) = 0\) and the regression equation reduces to the following.

\[\begin{array}{rcl} E(\textrm{FG} | \textrm{WC}, \textrm{Gender = Male}) & = & 6.233 \\ & + & 0.040 \times (\textrm{WC} - 100) \end{array}\]

For females, \(I(\textrm{Gender} = \textrm{Female})=1\), so the regression equation reduces to the following.

\[\begin{array}{rcl} E(\textrm{FG} | \textrm{WC}, \textrm{Gender = Female}) & = & (6.233 - 0.290) \\ & + & (0.040 - 0.020) \times (\textrm{WC} - 100) \\ & = & 5.943 \\ & + & 0.020 \times (\textrm{WC} - 100) \end{array}\]

For males:

**Intercept:**Among males, the mean fasting glucose for those with WC = 100 is 6.233 mmol/L.**Coefficient for WC:**Among males, a 1 cm difference in WC is associated with a 0.040 mmol/L difference in fasting glucose.

For females:

**Intercept:**Among females, the mean fasting glucose for those with WC = 100 is 5.943 mmol/L.**Coefficient for WC:**Among females, a 1 cm difference in WC is associated with a 0.020 mmol/L difference in fasting glucose.

Thus, (1) among those with WC = 100 cm, females have a lower fasting glucose and (2) the association between WC and fasting glucose is about half as strong in females than males. In Section 5.9.5 we will visualize these differences to help assess their meaningfulness and in Section 5.9.6 we will test to see if these differences are statistically significant.

**NOTES:**

- When including an interaction with a continuous predictor, it is helpful to center the predictor first. For example, if we had not centered WC in the example above, everywhere where we have “WC = 100” would be “WC = 0” which is an impossible value.
- Centering helps for continuous predictors, not categorical. Also, for a continuous predictor \(X\), centering helps if \(X=0\) is not plausible, or when you want to see the value of the intercept or a main effect at some value of \(X\) other than 0.
- Failure to center a continuous predictor does
*not*invalidate the regression results – it just changes how you interpret them. The results are valid with or without centering.

### 5.9.5 Visualizing an interaction

Visualize the impact of including an interaction by plotting the regression lines for the models with and without an interaction. As in Section 4.7, plot the data, use `predict()`

to estimate the outcome values that fall on the regression lines over a range of predictor values, and plot those lines.

First, specify a range of continuous predictor values for plotting and assign the levels of the categorical predictor to an object.

```
# Values of the continuous predictor over which to plot
<- seq(min(nhanesf.complete$cBMXWAIST, na.rm = T),
cWC max(nhanesf.complete$cBMXWAIST, na.rm = T), by = 1)
# Levels of the categorical predictor
<- levels(nhanesf.complete$RIAGENDR) LEVELS
```

Next, create a `data.frame`

to contain predictions that has a row for each combination of the two predictors. `rep(cWC, length(LEVELS))`

repeats the entire range of `cWC`

values once for each level of gender. `rep(LEVELS, each=length(cWC))`

repeats each level of gender `length(cWC)`

times.

```
# Data frame of predictor values at which to predict
<- data.frame(
preddat # Repeat cWC for each level of gender
cBMXWAIST = rep(cWC, length(LEVELS)),
# Repeat the levels of gender for each value of cWC
RIAGENDR = rep(LEVELS, each=length(cWC))
)
```

**NOTE:** If there were additional predictors in the model, you would need to specify a single value for each of them in the `data.frame`

in order to obtain predictions. What values you choose for the other predictors will affect the estimated values you plot, but they will not affect the nature of the interaction so in that sense they are arbitrary.

We also include an uncentered version of the continuous predictor which we will need for plotting. To create an uncentered predictor from a centered one, simply add back in the centering value.

```
# Create uncentered predictor (for plotting)
$BMXWAIST <- preddat$cBMXWAIST + 100 preddat
```

Next, compute the predictions and add them to the `data.frame`

. This results in a `data.frame`

with all the `cWC`

values for males, followed by the same `cWC`

values for females, and a predicted outcome value at each combination. In this example, in order to illustrate the difference, we compute predictions for both the model with and without an interaction. Typically, you will only need to compute and plot the predictions from the interaction model. The first 10 rows are shown below.

```
# Add columns for the predicted values
$pred_no_int <- predict(fit.ex5.2.noint, preddat)
preddat$pred_int <- predict(fit.ex5.2.int, preddat)
preddat
# Examine the prediction data frame
head(preddat, 10)
```

```
## cBMXWAIST RIAGENDR BMXWAIST pred_no_int pred_int
## 1 -36.8 Male 63.2 5.220 4.753
## 2 -35.8 Male 64.2 5.248 4.793
## 3 -34.8 Male 65.2 5.276 4.833
## 4 -33.8 Male 66.2 5.304 4.873
## 5 -32.8 Male 67.2 5.333 4.913
## 6 -31.8 Male 68.2 5.361 4.954
## 7 -30.8 Male 69.2 5.389 4.994
## 8 -29.8 Male 70.2 5.417 5.034
## 9 -28.8 Male 71.2 5.446 5.074
## 10 -27.8 Male 72.2 5.474 5.115
```

Finally, create the plots. Make sure to `plot`

the raw (uncentered) continuous predictor.

```
par(mfrow=c(1,2))
# Subset for each gender
# Make sure this order is consistent with the legend below
<- preddat$RIAGENDR == "Male"
SUB1 <- preddat$RIAGENDR == "Female"
SUB2
# No interaction
# Plot the raw X variable, not the centered one
plot(nhanesf.complete$BMXWAIST, nhanesf.complete$LBDGLUSI, col = "gray",
xlab = "Waist Circumference (cm)",
ylab = "Fasting Glucose (mmol/L)",
las = 1, pch = 20, font.lab = 2, font.axis = 2)
# Add lines to the plot for each gender
lines(preddat$BMXWAIST[SUB1], preddat$pred_no_int[SUB1],
lwd = 2, lty = 1, col = "purple")
lines(preddat$BMXWAIST[SUB2], preddat$pred_no_int[SUB2],
lwd = 2, lty = 2, col = "dark green")
legend(100, 20, c("Male", "Female"), col=c("purple", "dark green"),
lwd=c(2,2), lty=c(1,2), bty="n")
# Interaction
# Plot the raw X variable, not the centered one
plot(nhanesf.complete$BMXWAIST, nhanesf.complete$LBDGLUSI, col = "gray",
xlab = "Waist Circumference (cm)",
ylab = "Fasting Glucose (mmol/L)",
las = 1, pch = 20, font.lab = 2, font.axis = 2)
# Add lines to the plot for each gender
lines(preddat$BMXWAIST[SUB1], preddat$pred_int[SUB1],
lwd = 2, lty = 1, col = "purple")
lines(preddat$BMXWAIST[SUB2], preddat$pred_int[SUB2],
lwd = 2, lty = 2, col = "dark green")
legend(100, 20, c("Male", "Female"), col=c("purple", "dark green"),
lwd=c(2,2), lty=c(1,2), bty="n")
```

**Model with no interaction:** In the *left panel* of Figure 5.15, the WC effect (slope) for males and females is *assumed* to be the same (and the estimate is 0.028, which comes from the model with no interaction `fit.ex5.2.noint`

), and the female line is slightly below the male line by an amount equal to the gender effect (-0.314, also from `fit.ex5.2.noint`

). The assumption of no interaction is equivalent to assuming that the lines are *parallel*.

**Model with an interaction:** In the *right panel*, including an interaction term has the effect of fitting separate regression lines for males and females. The WC slope for males (0.040) is much steeper than for females (0.020), indicating that WC has a greater effect on fasting glucose for males than for females.

Although it is a subjective judgment, visually it appears that the interaction is meaningfully large. In the next section, we will test to see if the magnitude of the interaction is statistically significant.

### 5.9.6 Testing the difference between the slopes

In the right panel of Figure 5.15, is the difference between the male and female slopes statistically significant? This is equivalent to asking “Are the lines in the plot significantly different from parallel?” Recall the regression equation for this interaction model.

\[ \textrm{FG} = \beta_0 + \beta_1 (\textrm{WC} - 100) + \beta_2 I(\textrm{Gender} = \textrm{Female}) + \beta_3 (WC - 100) I(Gender = Female) + \epsilon \]

The p-value for the regression coefficient for the interaction tests the null hypothesis \(H_0: \beta_3 = 0\). Under the null hypothesis, the lines are parallel. Thus, to test the difference between the slopes, examine the interaction p-value.

`round(summary(fit.ex5.2.int)$coef, 3)`

```
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.233 0.080 78.169 0.000
## cBMXWAIST 0.040 0.005 8.276 0.000
## RIAGENDRFemale -0.290 0.107 -2.704 0.007
## cBMXWAIST:RIAGENDRFemale -0.020 0.006 -3.218 0.001
```

From the output, the p-value for the test of interaction is .001. In this case, since the interaction was between a continuous predictor and a binary predictor, the interaction is just one term, so the test can be obtained directly from the regression coefficient table. In Section 5.9.10 we will discuss what to do when the interaction involves a categorical predictor with more than two levels.

Since p < .05, we can make the following two inferences:

- There is a significant difference in the WC effect on fasting glucose between males and females (the lines are significantly different from parallel).
- There is a significant difference in the gender effect on fasting glucose between those with differing WC (the vertical distance between the lines depends on how large or small is WC).

### 5.9.7 Estimating and testing the significance of the slope at each level of a moderator

We just showed that the WC effect is significantly greater for males than for females. What if you want to estimate and test the significance of the WC effect for each gender individually (testing whether the line for males is significantly different from a horizontal line and, separately, testing whether the line for females is significantly different from a horizontal line)?

The null hypothesis for the test of the WC effect among males is a test of the slope for males, \(H_0: \beta_1=0\). Since this involves just one regression coefficient, you can read this right off the output in the `cBMXWAIST`

row of the `COEFFICIENTS`

table since that row corresponds to \(\beta_1\). Thus, the WC effect for males is statistically significant (B = 0.040; 95% CI = 0.031, 0.050; p < .001).

However, the slope for females is the sum of two regression coefficients (\(\beta_1\) and \(\beta_3\)). How do we conduct the test for females? You *could* refit the model after setting “Female” to be the reference level instead of “Male”. In this new model, the WC main effect would be the slope for females. However there is a more generally applicable method that is useful to learn and does not involve refitting the model.

In our current model, in which “Male” was the reference level for gender, the test of the WC effect among females is \(H_0: \beta_1 + \beta_3 = 0\). The function `gmodels::estimable()`

(Warnes et al. 2022) can be used to estimate and test any linear combination of regression coefficients. To use this function with a model with four regression coefficients (including the intercept), specify a vector \((a, b, c, d)\) corresponding to the linear combination \(a\beta_0 + b\beta_1 + c\beta_2 + d\beta_3\) of interest. The function will then estimate this sum and test the null hypothesis that it is 0. For females, since we want to test \(\beta_1 + \beta_3\), our vector is \((0, 1, 0, 1)\).

**NOTE:** When using `gmodels::estimable()`

to estimate the effect of \(X\) at levels of \(Z\), always include a 1 in the slot for the main effect of \(X\), do *not* include a 1 for the main effect of \(Z\), and include the value of \(Z\) in the slot for the \(X \times Z\) interaction. In this example, \(X\) is WC and \(Z\) is \(I(\textrm{Gender} = \textrm{Female})\), so we include a 1 in the WC main effect slot (slot 2) and a 1 or 0 in the interaction slot (slot 4) depending on whether gender is female or male.

To make sure you are putting the numbers in the correct slots, look at the number, order, and spelling of the coefficients in the `lm`

object. In the code below, the vector specifying the linear combination is a named vector. The names are not required, but are a good idea to ensure the correct numbers are entered in the correct slots.

```
# Number of coefficients
length(coef(fit.ex5.2.int))
```

`## [1] 4`

```
# Select the 1st column
# Include drop=F to keep it as a matrix (which displays vertically)
summary(fit.ex5.2.int)$coef[, 1, drop=F]
```

```
## Estimate
## (Intercept) 6.23335
## cBMXWAIST 0.04024
## RIAGENDRFemale -0.29038
## cBMXWAIST:RIAGENDRFemale -0.02036
```

```
# Test slope for females
::estimable(fit.ex5.2.int,
gmodelsc("(Intercept)" = 0,
"cBMXWAIST" = 1,
"RIAGENDRFemale" = 0,
"cBMXWAIST:RIAGENDRFemale" = 1),
conf.int = 0.95)
```

```
## Estimate Std. Error t value DF Pr(>|t|) Lower.CI Upper.CI
## (0 1 0 1) 0.01988 0.004051 4.907 853 0.000001106 0.01193 0.02783
```

Any terms omitted will be assumed to be multiplied by zero. Thus, the following abbreviated code produces the same result.

```
::estimable(fit.ex5.2.int,
gmodelsc("cBMXWAIST" = 1,
"cBMXWAIST:RIAGENDRFemale" = 1),
conf.int = 0.95)
```

You can also get the same answer without naming the terms, but then you must include all the slots. However, use this method with caution as without names it is easy to enter values in the wrong slots.

`::estimable(fit.ex5.2.int, c(0,1,0,1), conf.int = 0.95) gmodels`

Although we already tested the slope for males above, we could use `gmodels::estimable()`

instead. For males, the vector would be \((0, 1, 0, 0)\) (to test \(H_0: \beta_1=0\)).

```
# Test slope for males
# Optionally, round the output
round(
::estimable(fit.ex5.2.int,
gmodelsc("(Intercept)" = 0,
"cBMXWAIST" = 1,
"RIAGENDRFemale" = 0,
"cBMXWAIST:RIAGENDRFemale" = 0),
conf.int = 0.95)
4) ,
```

```
## Estimate Std. Error t value DF Pr(>|t|) Lower.CI Upper.CI
## (0 1 0 0) 0.0402 0.0049 8.276 853 0 0.0307 0.0498
```

**Conclusion:** The WC effects for males (Est = 0.040; 95% CI = 0.031, 0.050; p < .001) and females (Est = 0.020; 95% CI = 0.012, 0.028; p < .001) are each statistically significant.

### 5.9.8 A two-way interaction has two interpretations

Above, we saw how the WC effect differed by gender. We can also break down the regression equation by WC to see how the gender effect differs by WC. Let’s see what the equations look like at WC = 80, 100, and 120 cm.

To get the regression equation at WC = 80, plug this value into Equation (5.2) to get the following.

\[\begin{array}{rcl} E(\textrm{FG} | \textrm{WC} = 80, \textrm{Gender}) & = & 6.233 \\ & + & 0.040 \times (80 - 100) \\ & - & 0.290 \times I(\textrm{Gender} = \textrm{Female}) \\ & - & 0.020 \times (80 - 100) \times I(\textrm{Gender} = \textrm{Female}) \end{array}\]

which reduces to

\[ E(\textrm{FG} │ \textrm{WC}=80, \textrm{Gender}) = 5.429 + 0.117 \times I(\textrm{Gender}=\textrm{Female}) \]

The math was carried out before rounding so you may get a different answer if you start with the values rounded to three digits. Similarly, for the other WC values, we get the following.

\[\begin{array}{rcl} E(\textrm{FG} │ \textrm{WC}=100, \textrm{Gender}) & = & 6.233 - 0.290 \times I(\textrm{Gender}=\textrm{Female}) \\ E(\textrm{FG} │ \textrm{WC}=120, \textrm{Gender}) & = & 7.038 - 0.698 \times I(\textrm{Gender}=\textrm{Female}) \end{array}\]

As WC increases from 80 to 120 cm (a total of 40 cm), the gender effect changes by 40 \(\times\) the interaction effect, or \(40 \times -0.0204=-0.8145\), going from 0.1169 to -0.6976. Visualize this in the plot by looking at how far apart the Male and Female regression lines are at different WC values, as show in Figure 5.16.

**Conclusion:** The magnitude of the association between WC and fasting glucose differs significantly between males and females (p = .001) (this is the p-value for the interaction). The association between WC and fasting glucose is significant for both males (Slope = 0.040; 95% CI = 0.031, 0.050; p < .001) and females (Slope = 0.020; 95% CI = 0.012, 0.028; p < .001), but is significantly lower for females (B-interaction (difference in slopes) = -0.020; 95% CI = -0.033, -0.008; p = .001).

If you feel confused by interactions, you are not alone! Assuming your confusion is not due to the author’s lack of clarity, take comfort in the fact that interactions are inherently tricky, but you will learn and get used to them with experience. They are easy to mis-understand and mis-interpret, so if you feel confused that is a good thing in one respect – it means you know enough to be careful and ask for help until you are comfortable dealing with interactions on your own.

### 5.9.9 Types of two-way interactions

In regression, you can have the following different kinds of two-way interactions:

- Interaction between a continuous predictor and a categorical predictor
- Interaction between two categorical predictors
- Interaction between two continuous predictors

#### 5.9.9.1 Continuous \(\times\) categorical

This is the type of interaction discussed in Example 5.2 in Sections 5.9.1 to 5.9.8 (WC \(\times\) gender).

#### 5.9.9.2 Categorical \(\times\) categorical

An interaction between two categorical predictors can be more complicated. For example, if you have a categorical predictor with 2 levels interacted with a categorical predictor with 3 levels, you do not have two regression lines but rather 2 \(\times\) 3 = 6 means. In addition, it is possible that even if neither predictor was sparse enough to warrant collapsing levels, one or the other might be sparse within levels of the other.

**Example 5.3** Regress fasting glucose on gender and income, along with their interaction, interpret the regression coefficients, and visualize the interaction.

First, check to see if any combination of these predictors is sparse.

`table(nhanesf.complete$RIAGENDR, nhanesf.complete$income)`

```
##
## < $25,000 $25,000 to < $55,000 $55,000+
## Male 67 106 215
## Female 90 115 264
```

All combinations have relatively large sample sizes. If some combination had a very small sample size, then one or more of the interaction terms would be estimated very imprecisely. In that case, it might be a good idea to collapse one or more of the predictors involved in the interaction (see Section 5.4.5).

The syntax for fitting this model is the same as for the continuous \(\times\) categorical model.

```
3.int <- lm(LBDGLUSI ~ RIAGENDR + income +
fit.ex5.:income,
RIAGENDRdata = nhanesf.complete)
round(summary(fit.ex5.3.int)$coef, 3)
```

```
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.233 0.199 31.266 0.000
## RIAGENDRFemale 0.216 0.263 0.820 0.413
## income$25,000 to < $55,000 0.101 0.255 0.396 0.693
## income$55,000+ 0.102 0.228 0.447 0.655
## RIAGENDRFemale:income$25,000 to < $55,000 -0.712 0.343 -2.077 0.038
## RIAGENDRFemale:income$55,000+ -0.742 0.303 -2.448 0.015
```

Including the intercept, there are 6 coefficients above. These can be combined to estimate mean fasting glucose at the 6 possible combinations of gender \(\times\) income. Let’s compute the mean at each level. We *could* use `gmodels::estimable()`

but for estimating the mean outcome at levels of categorical predictors (as opposed to the slopes of continuous predictors, which are not estimated means) using `predict()`

is much easier.

```
# Get levels of each categorical predictors
<- levels(nhanesf.complete$income)
LEVELS1 <- levels(nhanesf.complete$RIAGENDR)
LEVELS2
# Create a data.frame to store the predictions
<- data.frame(
preddat income = rep(LEVELS1, length(LEVELS2)),
RIAGENDR = rep(LEVELS2, each=length(LEVELS1))
)
# Add the predictions
$pred <- predict(fit.ex5.3.int, preddat)
preddat
# View the predicted means
preddat
```

```
## income RIAGENDR pred
## 1 < $25,000 Male 6.233
## 2 $25,000 to < $55,000 Male 6.334
## 3 $55,000+ Male 6.335
## 4 < $25,000 Female 6.449
## 5 $25,000 to < $55,000 Female 5.837
## 6 $55,000+ Female 5.809
```

We can also visualize these means, as shown in Figure 5.17. Compare the rows of `preddat`

to the plotted means to verify that the plotting code is correct.

```
# Plot fasting glucose vs. income (LEVELS1),
# with separate means by gender (LEVELS2)
plot.default(nhanesf.complete$income, nhanesf.complete$LBDGLUSI,
xlab = "Income", ylab = "Fasting Glucose (mmol/L)",
las = 1, pch = 20, col = "gray",
font.lab = 2, font.axis = 2, xaxt = "n")
axis(1, at = 1:3, labels = LEVELS1, font = 2)
# Add means to the plot for males
points(1:3, preddat$pred[preddat$RIAGENDR == "Male"],
col = "purple", pch = 19, cex = 1.5)
lines( 1:3, preddat$pred[preddat$RIAGENDR == "Male"],
col = "purple", lty = 1)
# Add means to the plot for females
points(1:3, preddat$pred[preddat$RIAGENDR == "Female"],
col = "dark green", pch = 17, cex = 1.5)
lines( 1:3, preddat$pred[preddat$RIAGENDR == "Female"],
col = "dark green", lty = 2)
legend(1.1, 17, c("Male", "Female"), title = "Gender",
lty = c(1,2), col = c("purple", "dark green"),
pch = c(19, 17), pt.cex = 1.5, seg.len = 5, bty = "n")
```

Is the interaction statistically significant? When you have an interaction between categorical predictors with \(L_1\) and \(L_2\) levels, there will be \((L_1-1) \times (L_2-1)\) interaction terms. If this product is > 1, which it will be if either categorical predictor has more than two levels, then you cannot get this test from the default `lm()`

output since it is a multiple degree of freedom test (you are testing more than one coefficient simultaneously). But you can get it using `car::Anova()`

.

`::Anova(fit.ex5.3.int, type = 3) car`

```
## Anova Table (Type III tests)
##
## Response: LBDGLUSI
## Sum Sq Df F value Pr(>F)
## (Intercept) 2603 1 977.55 <0.0000000000000002 ***
## RIAGENDR 2 1 0.67 0.413
## income 1 2 0.11 0.898
## RIAGENDR:income 17 2 3.17 0.042 *
## Residuals 2266 851
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
```

We conclude that there is a statistically significant interaction between gender and smoking status (p = .042). From Figure 5.17, we see that females have a greater mean fasting glucose among those with income \(<\) $25,000 but a lower mean fasting glucose among those with \(\ge\) $25,000.

**What if you want to estimate the difference between specific levels of one predictor at a certain level of the other?**

For example, estimate the difference in mean fasting glucose between males and females among those with different incomes.

- The main effect regression coefficient for
`RIAGENDRFemale`

is the difference in mean fasting glucose between females and males at the reference level of income, which is < $25,000. - The difference in mean outcome between females and males among those making $25,000 to < $55,000 is the sum of the
`RIAGENDRFemale`

main effect and the`RIAGENDRFemale:income$25,000 to < $55,000`

interaction term. - The difference in mean outcome between females and males among those making $55,000+ is the sum of the
`RIAGENDRFemale`

main effect and the`RIAGENDRFemale:income$55,000+`

interaction term.

Since these are sums of coefficients, use `gmodels::estimable()`

to estimate these effects. First, look at the coefficient vector to confirm the number, order, and spelling of the terms in the model.

`length(coef(fit.ex5.3.int))`

`## [1] 6`

`summary(fit.ex5.3.int)$coef[, 1, drop=F]`

```
## Estimate
## (Intercept) 6.2328
## RIAGENDRFemale 0.2158
## income$25,000 to < $55,000 0.1007
## income$55,000+ 0.1021
## RIAGENDRFemale:income$25,000 to < $55,000 -0.7122
## RIAGENDRFemale:income$55,000+ -0.7418
```

There are 6 slots. The gender main effect is `RIAGENDRFemale`

and the interaction terms are `RIAGENDRFemale:income$25,000 to < $55,000`

and `RIAGENDRFemale:income$55,000+`

. Since we are estimating gender effects at levels of income, always assign a 1 to the gender main effect slot, and assign a 0 or 1 to each interaction term, depending on the level of income.

```
rbind(
# Females vs. Males, Income < $25,000
# (income reference level, so no 1 in any interaction slot)
::estimable(fit.ex5.3.int,
gmodelsc("RIAGENDRFemale" = 1),
conf.int = 0.95),
# Females vs. Males, Income $25,000 to < $55,000
::estimable(fit.ex5.3.int,
gmodelsc("RIAGENDRFemale" = 1,
"RIAGENDRFemale:income$25,000 to < $55,000" = 1),
conf.int = 0.95),
# Females vs. Males, Income $55,000+
::estimable(fit.ex5.3.int,
gmodelsc("RIAGENDRFemale" = 1,
"RIAGENDRFemale:income$55,000+" = 1),
conf.int = 0.95)
)
```

```
## Estimate Std. Error t value DF Pr(>|t|) Lower.CI Upper.CI
## (0 1 0 0 0 0) 0.2158 0.2633 0.8197 851 0.4126023 -0.3010 0.73262
## (0 1 0 0 1 0) -0.4964 0.2197 -2.2592 851 0.0241231 -0.9276 -0.06513
## (0 1 0 0 0 1) -0.5260 0.1499 -3.5087 851 0.0004739 -0.8202 -0.23174
```

Equivalently, you could use the following code. It is a matter of preference which form you use. The former is less error-prone in that the slots are named and you do not have to keep track of the position of the slots. Also, the former is more intuitive if you understand what is needed as “main effect + an interaction term.” However, the latter is nice in that it is easy to see the similarities and differences between the three vectors since they are lined up. They all have a 1 in the main effect slot, the first has no 1 in any interaction slot, and the remaining have a 1 in consecutive interaction slots.

```
rbind(
::estimable(fit.ex5.3.int, c(0, 1, 0, 0, 0, 0), conf.int = 0.95),
gmodels::estimable(fit.ex5.3.int, c(0, 1, 0, 0, 1, 0), conf.int = 0.95),
gmodels::estimable(fit.ex5.3.int, c(0, 1, 0, 0, 0, 1), conf.int = 0.95)
gmodels )
```

**Conclusion:**

- Among those making < $25,000 per year, fasting glucose is greater in females than males, although this difference is not statistically significant (Est = 0.22; 95% CI = -0.30, 0.73; p = .413).
- Among those making $25,000 to < $55,000 per year, fasting glucose is significantly lower in females than males (Est = -0.50; 95% CI = -0.93, -0.07; p = .024).
- Among those making $55,000 or more per year, fasting glucose is significantly lower in females than males (Est = -0.53; 95% CI = -0.82, -0.23; p < .001).

#### 5.9.9.3 Continuous \(\times\) continuous

An interaction between two continuous predictors is simpler in one way but more complicated in another. It will always involve just one regression coefficient, but the relationship cannot be *completely* visualized as a pair of regression lines. Since each predictor is continuous, with more than just a few possible values, the complete visualization would actually be a response surface. But, to partially illustrate the interaction, you can plot a regression line for one predictor at a set of specific values of the other (like we did for the continuous \(\times\) categorical interaction).

**Example 5.4:** Regress fasting glucose on the continuous predictors waist circumference and age, along with their interaction, and interpret the regression coefficients. Center age at 40 years and WC at 100 cm. After fitting the model, visualize the association between waist circumference and fasting glucose for those age 30, 40, and 50 years.

The regression equation is

\[\textrm{FG} = \beta_0 + \beta_1 (\textrm{Age}-40) + \beta_2 (\textrm{WC}-100) + \beta_3 (\textrm{Age}-40) (\textrm{WC}-100) + \epsilon\]

and the interpretation of each parameter is as follows.

- \(\beta_0\) is the mean fasting glucose among those age 40 years with WC = 100 cm.
- \(\beta_1\) is the age effect among those with WC = 100 cm. Because there is an Age \(\times\) WC interaction, the “age effect” varies with WC.
- \(\beta_2\) is the WC effect among those age 40 years. Because there is an Age \(\times\) WC interaction, the “WC effect” varies with age.
- \(\beta_3\) is the interaction effect. It represents the difference in the age effect for every cm of WC away from 100 cm, and the difference in the WC effect for every year of age away from 40 years.

Fitting the model is no different than with other forms of interactions.

```
# Centering
<- nhanesf.complete %>%
nhanesf.complete mutate(cRIDAGEYR = RIDAGEYR - 40,
cBMXWAIST = BMXWAIST - 100)
# Fit model
4.int <- lm(LBDGLUSI ~ cRIDAGEYR + cBMXWAIST +
fit.ex5.:cBMXWAIST,
cRIDAGEYRdata = nhanesf.complete)
# View output
round(summary(fit.ex5.4.int)$coef, 4)
```

```
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.8915 0.0581 101.358 0.0000
## cRIDAGEYR 0.0223 0.0032 6.967 0.0000
## cBMXWAIST 0.0233 0.0032 7.297 0.0000
## cRIDAGEYR:cBMXWAIST 0.0005 0.0002 2.903 0.0038
```

As mentioned, the interaction is a single term in the model so the test of significance of the interaction can be read right off the output (interaction p = .004). That is the simple aspect of a continuous \(\times\) continuous interaction. The complicated aspect is that to visualize this model fully requires a 3-dimensional plot. However, we can pick a few specific values of one predictor and plot the regression lines for the other predictor at those levels. This is what we did for a continuous \(\times\) categorical interaction but in that case there were a finite number of categorical levels; here, there are an infinite number of values you can pick from, so for this Example we just picked a few interesting values (ages 30, 40 and 50 years).

Once again, use predict to get the fitted values over a range and then plot. In this example, after a first try, the legend was re-ordered to match the order of the lines in the plot.

```
# Regression lines for glucose vs. WC at ages 30, 40 and 50 years
# Specify a range of continuous predictor values for plotting
<- seq(min(nhanesf.complete$cBMXWAIST, na.rm = T),
cWC max(nhanesf.complete$cBMXWAIST, na.rm = T), by = 1)
# Data frame of values at which to predict
<- data.frame(cBMXWAIST = rep(cWC, 3), # Repeat for 3 ages
preddat # Each age (30,40,50) is centered at 40
# Repeat each length(cWC) times
cRIDAGEYR = c(rep(30 - 40, length(cWC)),
rep(40 - 40, length(cWC)),
rep(50 - 40, length(cWC))))
# Create uncentered predictors (for plotting)
$BMXWAIST <- preddat$cBMXWAIST + 100
preddat$RIDAGEYR <- preddat$cRIDAGEYR + 40
preddat
# Add columns for the predicted values
$pred <- predict(fit.ex5.4.int, preddat)
preddat
# Regression lines for Glucose vs. WC at ages 30, 40 and 50 years
# Plot the raw X variable, not the centered one
plot(nhanesf.complete$BMXWAIST, nhanesf.complete$LBDGLUSI,
xlab = "Waist Circumference (cm)",
ylab = "Fasting Glucose (mmol/L)", col = "lightgray",
las = 1, pch = 20, font.lab = 2, font.axis = 2)
# Add lines to the plot
<- preddat$RIDAGEYR == 30
SUB1 <- preddat$RIDAGEYR == 40
SUB2 <- preddat$RIDAGEYR == 50
SUB3 lines(preddat$BMXWAIST[SUB1], preddat$pred[SUB1], lwd=2, lty=1, col="blue")
lines(preddat$BMXWAIST[SUB2], preddat$pred[SUB2], lwd=2, lty=2, col="magenta")
lines(preddat$BMXWAIST[SUB3], preddat$pred[SUB3], lwd=2, lty=3, col="brown")
# # First try
# legend(60, 18,
# c("30", "40", "50"),
# col=c("blue", "magenta", "brown"),
# lty=c(1,2,3),
# title = "Age (years)", cex = 0.9, lwd=2, bty="n")
# After looking at the plot, use [] notation to order the legend,
# col, and lty to match the order of the lines from top to bottom
<- c(3,2,1)
ORDER legend(60, 18,
c("30", "40", "50")[ORDER],
col=c("blue", "magenta", "brown")[ORDER],
lty=c(1,2,3)[ORDER],
title = "Age (years)", cex = 0.9, lwd=2, bty="n")
```

Recall that the regression coefficient table is the following.

`round(summary(fit.ex5.4.int)$coef, 4)`

```
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.8915 0.0581 101.358 0.0000
## cRIDAGEYR 0.0223 0.0032 6.967 0.0000
## cBMXWAIST 0.0233 0.0032 7.297 0.0000
## cRIDAGEYR:cBMXWAIST 0.0005 0.0002 2.903 0.0038
```

We can interpret the numbers in this table in light of Figure 5.18.

- The coefficient for
`cBMXWAIST`

is 0.0233. This is the slope for fasting glucose vs. WC when Age = 40 years (the value at which we centered age) and corresponds to the slope of the dashed (middle) line. - The interaction term is statistically significant (p = .004). Thus, we can reject the null hypothesis that the lines are parallel, and conclude that the age effect varies with WC, and the WC effect varies with age.
- The interaction term is positive (0.0005). This means that
- the slope is larger among those who are older, as can be seen by the fact that lines become more steep at older age; and
- differences in fasting glucose between those of different ages are greater among those with greater WC (the lines are further apart for larger WC values).

**What if you want to estimate the WC slopes at each of these ages?**

The WC slope at a given age is the `cBMXWAIST`

main effect plus the (centered) age times the `cRIDAGEYR:cBMXWAIST`

interaction. Use `gmodels::estimable()`

to estimate these effects. First, look at the coefficient vector to confirm the number, order, and spelling of the terms in the model.

`length(coef(fit.ex5.4.int))`

`## [1] 4`

`summary(fit.ex5.4.int)$coef[, 1, drop=F]`

```
## Estimate
## (Intercept) 5.8915185
## cRIDAGEYR 0.0223365
## cBMXWAIST 0.0232526
## cRIDAGEYR:cBMXWAIST 0.0005434
```

There are 4 slots. The WC main effect is in slot 3, and the interaction term is in slot 4. While we still enter a 1 in the main effect slot (as in all our previous examples), in the interaction slot we enter the (centered) age value rather than a 1 (since age is continuous). Since we centered age at 40 years, instead of entering 30, 40, and 50 in slot 4, enter 30-40, 40-40, and 50-40. With only four slots, it is not difficult to correctly specify the vectors without naming, so we use the non-named format for this example.

```
round(rbind(
::estimable(fit.ex5.4.int,
gmodelsc("cBMXWAIST" = 1,
"cRIDAGEYR:cBMXWAIST" = 30-40),
conf.int = 0.95),
::estimable(fit.ex5.4.int,
gmodelsc("cBMXWAIST" = 1,
"cRIDAGEYR:cBMXWAIST" = 40-40),
conf.int = 0.95),
::estimable(fit.ex5.4.int,
gmodelsc("cBMXWAIST" = 1,
"cRIDAGEYR:cBMXWAIST" = 50-40),
conf.int = 0.95)
6) ),
```

```
## Estimate Std. Error t value DF Pr(>|t|) Lower.CI Upper.CI
## (0 0 1 -10) 0.01782 0.004105 4.340 853 0.000016 0.009761 0.02588
## (0 0 1 0) 0.02325 0.003186 7.297 853 0.000000 0.016998 0.02951
## (0 0 1 10) 0.02869 0.003234 8.871 853 0.000000 0.022339 0.03503
```

**Conclusion:**

- Among those age 30 years, those with 1-unit greater WC have, on average, a fasting glucose that is 0.0178 greater (Est = 0.0178; 95% CI = 0.0098, 0.0259; p < .001).
- Among those age 40 years, those with 1-unit greater WC have, on average, a fasting glucose that is 0.0233 greater (Est = 0.0233; 95% CI = 0.0170, 0.0295; p < .001).
- Among those age 50 years, those with 1-unit greater WC have, on average, a fasting glucose that is 0.0287 greater (Est = 0.0287; 95% CI = 0.0223, 0.0350; p < .001).

### 5.9.10 Test of interaction

This section reviews the methods for carrying out test of significance of the interaction term. We already carried out this test for each type of interaction in the previous sections, but the method is summarized here.

For a regression with outcome \(Y\) and an interaction between \(X\) and \(Z\), a statistical test of interaction is a test of the null hypothesis that the magnitude of the effect of \(X\) on \(Y\) does not depend on \(Z\), and that the magnitude of the effect of \(Z\) on \(Y\) does not depend on \(X\). Visually, the null hypothesis corresponds to parallel lines in plots such as Figures 5.15, 5.17, and 5.18. This corresponds to the null hypothesis that the regression coefficients that define the interaction are all zero.

When the interaction involves just one term in the model (one row in the regression coefficient table) you can get the p-value for the interaction test by looking at the regression table. For example, if the regression formula is \(Y = \beta_0 + \beta_1 X + \beta_2 Z + \beta_3 XZ + \epsilon\), the null hypothesis is \(H_0: \beta_3 = 0\). In our example of an interaction between two continuous predictors, we would look in the row with the term that contains a `:`

(`cRIDAGEYR:cBMXWAIST`

).

`round(summary(fit.ex5.4.int)$coef, 4)`

```
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.8915 0.0581 101.358 0.0000
## cRIDAGEYR 0.0223 0.0032 6.967 0.0000
## cBMXWAIST 0.0233 0.0032 7.297 0.0000
## cRIDAGEYR:cBMXWAIST 0.0005 0.0002 2.903 0.0038
```

When at least one of the terms in the interaction is a categorical predictor with more than two levels, the interaction will consist of multiple terms. For example, if \(Z\) is categorical with levels 1 (the reference level), 2, and 3, the regression formula is

\[Y = \beta_0 + \beta_1 X + \beta_2 I(Z=2) + \beta_3 I(Z=3) + \beta_4 X \times I(Z=2) + \beta_5 X \times I(Z=3) + \epsilon\]

and the null hypothesis of no interaction is \(H_0: \beta_4 = 0 \textrm{ and } \beta_5 = 0\). In our example of an interaction between two categorical predictors, one of which had more than two levels, the rows with the `:`

terms do *not* provide the interaction test, as they are tests of each of the interaction terms individually.

`round(summary(fit.ex5.3.int)$coef, 4)`

```
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.2328 0.1994 31.2658 0.0000
## RIAGENDRFemale 0.2158 0.2633 0.8197 0.4126
## income$25,000 to < $55,000 0.1007 0.2547 0.3956 0.6925
## income$55,000+ 0.1021 0.2283 0.4472 0.6549
## RIAGENDRFemale:income$25,000 to < $55,000 -0.7122 0.3429 -2.0768 0.0381
## RIAGENDRFemale:income$55,000+ -0.7418 0.3030 -2.4483 0.0146
```

Recall that to test the main effect for a categorical predictor with more than two levels, we used `car::Anova()`

to carry out the multiple df test. We can do the same for a multiple df interaction:

`::Anova(fit.ex5.3.int, type = 3) car`

```
## Anova Table (Type III tests)
##
## Response: LBDGLUSI
## Sum Sq Df F value Pr(>F)
## (Intercept) 2603 1 977.55 <0.0000000000000002 ***
## RIAGENDR 2 1 0.67 0.413
## income 1 2 0.11 0.898
## RIAGENDR:income 17 2 3.17 0.042 *
## Residuals 2266 851
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
```

We conclude for this example that there is a significant gender \(\times\) income interaction (F[2, 851] = 3.17, p = .042). The same method (`car::Anova()`

) would be used for a continuous \(\times\) categorical interaction if the categorical predictor has more than two levels.

By way of reminder, the tests of each of the two main effects are *not* tests of the overall effect of each of those predictors. They are, rather, tests of significance of each at the reference level of the other. The following subsection will discuss how to obtain an appropriate overall test for each predictor involved in an interaction.

### 5.9.11 Overall test of a predictor involved in an interaction

In Section 5.9.10, we assessed the significance of an interaction with a test of the null hypothesis that one predictor effect does not vary with another predictor. A test of interaction answers a question such as “Does the effect of waist circumference on fasting glucose depend on gender?”

But what if we want to answer the question “Is waist circumference significantly associated with fasting glucose?” in a model which contains WC interacted with another predictor? This is a comparison of two models – one that includes WC and one that does not. When there is no interaction, this would simply be a test of the WC regression coefficient. When there is an interaction, however, this is a simultaneous test of the WC main effect and the WC interaction with the other predictor.

For example, if the model is

\[\textrm{FG} = \beta_0 + \beta_1 \textrm{WC} + \beta_2 I(\textrm{Gender} = \textrm{Female}) + \beta_3 \textrm{WC} \times I(\textrm{Gender} = \textrm{Female}) + \epsilon\]

the null hypothesis we would like to test is \(H_0: \beta_1 = 0\) and \(\beta_3 = 0\). We cannot use `car::Anova()`

for this test because these coefficients are from different terms in the model. Instead, to carry out this test, use `anova()`

(lower case “a”), which compares two nested models: a full model compared to a reduced model with some terms from the full model removed. In this example, we want to compare the full model (with both main effects and the interaction) to the model that does not have WC at all (excludes both the WC main effect and the interaction, but retains the gender main effect).

```
# Fit the reduced model
<- lm(LBDGLUSI ~ RIAGENDR, data = nhanesf.complete)
fit0 # Compare reduced and full models
anova(fit0, fit.ex5.2.int)
```

```
## Analysis of Variance Table
##
## Model 1: LBDGLUSI ~ RIAGENDR
## Model 2: LBDGLUSI ~ cBMXWAIST + RIAGENDR + cBMXWAIST:RIAGENDR
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 855 2295
## 2 853 2071 2 225 46.3 <0.0000000000000002 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
```

Thus, we conclude that the model with both WC and a WC \(\times\) gender interaction is significantly better than the model with just gender (F[2,853] = 46.3, p < .001), or that WC is significantly associated with fasting glucose.

**NOTE:** We are using a complete case analysis, so there are no missing values. However, if you had fit the full model to a dataset that contained missing values, then the reduced model might have a different sample size and `anova()`

would return an error. For example, using the `nhanesf`

dataset, which contains cases with missing waist circumference, we get an error.

`summary(nhanesf$BMXWAIST)`

```
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 63.2 88.3 97.8 100.5 111.0 169.5 35
```

```
2.int.missing <- lm(LBDGLUSI ~ BMXWAIST + RIAGENDR +
fit.ex5.:RIAGENDR, data = nhanesf)
BMXWAIST<- lm(LBDGLUSI ~ RIAGENDR, data = nhanesf)
fit0.missing anova(fit0.missing, fit.ex5.2.int.missing)
```

```
## Error in anova.lmlist(object, ...) :
## models were not all fitted to the same size of dataset
```

To be able to run `anova()`

without an error, either use the same complete case dataset for both the full and reduced models, or use the `subset`

option to remove cases with missing values on the predictor that was removed in the reduced model.

```
<- lm(LBDGLUSI ~ RIAGENDR, data = nhanesf,
fit0.missing subset = !is.na(BMXWAIST))
anova(fit0.missing, fit.ex5.2.int.missing)
```

```
## Analysis of Variance Table
##
## Model 1: LBDGLUSI ~ RIAGENDR
## Model 2: LBDGLUSI ~ BMXWAIST + RIAGENDR + BMXWAIST:RIAGENDR
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 963 2415
## 2 961 2192 2 223 48.9 <0.0000000000000002 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
```

### 5.9.12 When to include an interaction

If a research question is of the form “Does the association between the outcome \(Y\) and predictor \(X\) depend on (some other variable) \(Z\)?”, then the regression model used to answer the question must include an interaction between \(X\) and \(Z\). In that case, there is an *a priori* interaction of interest. In general, when carrying out a confirmatory analysis (see Section 5.22), use subject-matter knowledge to *a priori* decide which interactions to include, and then leave them in the model regardless of their statistical significance. Testing candidate interactions and only including those that are statistically significant can result in biased conclusions about statistical significance unless one uses advanced techniques to obtain valid inferences that account for the method of data exploration (Faraway 1992; Harrell 2015).

What if, rather than having specific interactions you want to test, you are interested in exploring many possible interactions, and finding a model that includes only interactions that seem meaningful? In an exploratory analysis (see Section 5.22), it is acceptable to try different interactions and include or not include them based on statistical significance and/or the magnitude of the interaction effects. It is important, if using this approach, to explicitly state you are carrying out an exploratory analysis, state what criteria you used to determine which interactions to include in your final model, and note as a limitation that the p-values for all terms in the model (both main effects and interactions) may be biased due to the fact that the final model was not pre-specified and decisions regarding what terms to include were based on statistical significance and/or effect size.

### References

*Journal of Computational and Graphical Statistics*1 (3): 213–29. https://doi.org/10.2307/1390717.

*Regression Modeling Strategies*. 2nd ed. Switzerland: Springer International Publishing.

*Gmodels: Various r Programming Tools for Model Fitting*. https://CRAN.R-project.org/package=gmodels.