#load packages
library(tidyverse)
library(emmeans)
library(apaTables)
library(easystats)
library(broom)
Lab 10: Factorial Designs
Princeton University
Research scenario
Based on subjects’ self-reports of rejection sensitivity (N = 80), a researcher divides subjects into two equal groups (low RS and high RS). Whereas half of the subjects in each group interact with a partner who displays a happy emotional expression during the interaction, the other half of the subjects in each group interact with a partner who displays a neutral emotional expression during the interaction. After the interaction, subjects are asked to rate the statement, “My interaction partner likes me”, on a scale from 1 (strongly disagree) to 7 (strongly agree).
Factor 1: Rejection Sensitivity
- Low
- High
Factor 2: Partner’s Emotional Expression
- Neutral
- Happy
Dependent Variable: Perceived Liking
Import & inspect the data
- Load the .csv file from the repository
<- read.csv("https://raw.githubusercontent.com/jgeller112/Lab10-Interactions-2/main/reject.csv") reject
Make sure the categorical variables are factors
str(reject)
'data.frame': 80 obs. of 4 variables:
$ X : int 1 2 3 4 5 6 7 8 9 10 ...
$ rs : chr "Low " "Low " "Low " "Low " ...
$ partner: chr "Neutral " "Neutral " "Neutral " "Neutral " ...
$ liking : int 4 4 4 5 5 5 5 5 5 5 ...
<- reject %>%
reject_cat mutate(rs_cat=as.factor(rs), partner_cat=as.factor(partner))
str(reject_cat)
'data.frame': 80 obs. of 6 variables:
$ X : int 1 2 3 4 5 6 7 8 9 10 ...
$ rs : chr "Low " "Low " "Low " "Low " ...
$ partner : chr "Neutral " "Neutral " "Neutral " "Neutral " ...
$ liking : int 4 4 4 5 5 5 5 5 5 5 ...
$ rs_cat : Factor w/ 2 levels "High ","Low ": 2 2 2 2 2 2 2 2 2 2 ...
$ partner_cat: Factor w/ 2 levels "Happy ","Neutral ": 2 2 2 2 2 2 2 2 2 2 ...
- Notice that by default R orders factor levels alphabetically. In our case, this means that
High
will be the reference group of rejection sensitivity andHappy
will be the reference group of interaction partner’s emotional expression. However, it might be more intuitive to haveLow
andNeutral
be the reference groups, respectively.
Reorder the levels
<- reject_cat %>%
reject_cat mutate(rs_cat = factor(rs, levels=c("Low ", "High ")),
partner_cat = factor(partner,levels= c("Neutral ", "Happy ")))
Descriptive Statistics
- How many Ps are there per condition?
%>%
reject_cat group_by(rs_cat, partner_cat) %>%
summarise(n=n())
# A tibble: 4 × 3
# Groups: rs_cat [2]
rs_cat partner_cat n
<fct> <fct> <int>
1 "Low " "Neutral " 20
2 "Low " "Happy " 20
3 "High " "Neutral " 20
4 "High " "Happy " 20
Table of Means
- The results of a factorial ANOVA are often represented in a table of means, which contains the means of each combination of conditions (the cell means) and means for the levels of each variable ignoring the other variables (the marginal means)
Table of Means
- The apa.2way.table() function from the
apaTables
package is a very convenient way to get our cell means and marginal means. This function works for any type of 2-way ANOVA, regardless of the number of levels of your factors, e.g. it would work for a 3 x 3 ANOVA. All you need to do is indicate what the IV’s (aka factors) and DV are and specifyshow.marginal.means = TRUE
.
Use
apa.2way.table()
to create a table for our data
apa.2way.table(iv1 = rs_cat,
iv2 = partner_cat,
dv = liking,
data = reject_cat,
show.marginal.means = TRUE)
Table 0
Descriptive Statistics For Liking In a 2(Rs_cat) X 2(Partner_cat) Design
partner_cat
Neutral Happy Marginal
rs_cat M SD M SD M SD
Low 5.55 1.05 6.00 0.73 5.78 0.92
High 1.80 0.70 6.45 0.69 4.12 2.45
Marginal 3.67 2.09 6.22 0.73
Note. M = mean. SD = standard deviation.
Marginal indicates the means and standard deviations pertaining to main effects.
Question: Which means are being compared in the main effect of rejection sensitivity?
- 4.12 and 5.78
Question: Which means are being compared in the main effect of interaction partner?
- 6.22 and 3.67
Question:Which means are involved in the interaction?
- 6.45, 6.00, 1.80, 5.55
Conduct the Factorial ANOVA
Using Regression: lm
()
Run a dummy coded regression analysis
## your code here
<- lm(liking ~ rs_cat * partner_cat, data = reject_cat) %>%
model tidy(conf.int = TRUE)
model
# A tibble: 4 × 7
term estimate std.error statistic p.value conf.low conf.high
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 "(Intercept)" 5.55 0.180 30.9 9.26e-45 5.19 5.91
2 "rs_catHigh " -3.75 0.254 -14.8 5.19e-24 -4.26 -3.24
3 "partner_catHappy " 0.450 0.254 1.77 8.07e- 2 -0.0562 0.956
4 "rs_catHigh :partner… 4.20 0.359 11.7 1.21e-18 3.48 4.92
Interpret each of the regression coefficients
- \(b_0\): The predicted Y value for the neutral, low group (M=5.55)
- \(b_1\): The simple effect for the low vs. high group when neutral, b = -3.75, SE = 0.25, 95% CI[-4.26, -3.24], t = -14.75, p < .001.
- \(b_2\): The simple effect for the neutral vs. happy group when low, b = 0.45, SE = 0.25, 95% CI[-4.26, -3.24], p > .05.
- \(b_3\): The interaction between the rs and partner group, b = 4.20, SE = 0.36, 95% CI[-4.26, -3.24], p < .001.
Recoding
Obviously, the means being compared by b1 and b2 do not represent our main effects. The main effect of RS would be a comparison of the marginal means for the low and high conditions. The main effect of partner would be a comparison of the marginal means for the neutral and happy conditions.
With the way we have rs and partner coded in the model, the regression coefficient estimates don’t correspond simply to the mean difference between conditions. We can recode the factors so that the parameter estimates, b1 and b2, correspond to a test of the main effects.
Question: How should we code the levels of rejection sensitivity and partner emotion so that the parameter estimates, b1 and b2, correspond to a test of their main effects?
- Devaition coding
Assign new codes to the levels of each factor
#change to dev coding
contrasts(reject_cat$rs_cat)<-c(0.5, -0.5)
contrasts(reject_cat$partner_cat)<-c(0.5, -0.5)
Re-run the analysis with newly coded factors
<- lm(liking ~ rs_cat * partner_cat, data = reject_cat) %>%
model_dev tidy(conf.int = TRUE)
model_dev
# A tibble: 4 × 7
term estimate std.error statistic p.value conf.low conf.high
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 4.95 0.0899 55.1 5.14e-63 4.77 5.13
2 rs_cat1 1.65 0.180 9.18 6.03e-14 1.29 2.01
3 partner_cat1 -2.55 0.180 -14.2 4.64e-23 -2.91 -2.19
4 rs_cat1:partner_cat1 4.20 0.359 11.7 1.21e-18 3.48 4.92
Interpret the new model coefficients
- \(b_0\): The grand mean across all cell means
- \(b_1\): The main effect of rejection sensitivity, b = 1.65, SE = 0.18, 95% CI[-4.26, -3.24], t = 9.18, p < .001.
- \(b_2\): The main effect of partner , b = -2.55, SE = 0.18, 95% CI[-4.26, -3.24], t = 14.19, p < .001.
- \(b_3\): The interaction between the rs and partner group, b = 4.20, SE = 0.36, 95% CI[-4.26, -3.24], p < .001.
Using Traditional ANOVA: afex
- You can also perform a traditional ANOVA and get straightforward results by passing the model to the
aov_ez
function.
Run an ANOVA
library(afex)
<- read.csv("https://raw.githubusercontent.com/jgeller112/Lab10-Interactions-2/main/reject.csv")
reject
aov_ez(id="X", between=c("rs", "partner"), dv="liking", data=reject, anova_table = list(es = "pes"))
Anova Table (Type 3 tests)
Response: liking
Effect df MSE F pes p.value
1 rs 1, 76 0.65 84.28 *** .526 <.001
2 partner 1, 76 0.65 201.30 *** .726 <.001
3 rs:partner 1, 76 0.65 136.52 *** .642 <.001
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
## your code here
Question: What type of sums of squares does
aov_ez
use?
- Type 3
Effect sizes
What are the effect sizes for each main effect and interaction. For each effect, is it small, medium, or large?
## your code here
<- lm(liking ~ rs_cat * partner_cat, data = reject_cat) %>%
model_es ::eta_squared(partial=TRUE)
effectsize
model_es
# Effect Size for ANOVA (Type I)
Parameter | Eta2 (partial) | 95% CI
--------------------------------------------------
rs_cat | 0.53 | [0.40, 1.00]
partner_cat | 0.73 | [0.64, 1.00]
rs_cat:partner_cat | 0.64 | [0.54, 1.00]
- One-sided CIs: upper bound fixed at [1.00].
- All of them are large (huge!)
Power
Using
Superpower
determine the minimum/smallest effect size we could reliably detect given our sample size and design with 90% power
library(Superpower)
<- "2b*2b"
string <- 20
n
<- c(5.55, 6.00 ,1.80, 6.45)
mu <- c(1.05, 0.70, .73, .69)
sd <- c("rs", "Low", "High", "partner", "Neutral", "Happy") #
labelnames <- Superpower::ANOVA_design(design = string,
design_result n = n,
mu = mu,
sd = sd,
labelnames = labelnames,
plot = TRUE)
::ANOVA_power(design_result,
Superpoweralpha_level = 0.05,
nsims = 1000,
verbose = FALSE)
Power and Effect sizes for ANOVA tests
power effect_size
anova_rs 100 0.5274
anova_partner 100 0.7275
anova_rs:partner 100 0.6439
Power and Effect sizes for pairwise comparisons (t-tests)
power effect_size
p_rs_Low_partner_Neutral_rs_Low_partner_Happy 35.3 0.5217
p_rs_Low_partner_Neutral_rs_High_partner_Neutral 100.0 -4.2766
p_rs_Low_partner_Neutral_rs_High_partner_Happy 89.2 1.0492
p_rs_Low_partner_Happy_rs_High_partner_Neutral 100.0 -6.0451
p_rs_Low_partner_Happy_rs_High_partner_Happy 52.2 0.6677
p_rs_High_partner_Neutral_rs_High_partner_Happy 100.0 6.7441
Visualization
- Use
ggplot2
to create nice figures of the main effects and interaction
Main effects
Plotting the main effect of rejection sensitivity
## your code here
library(ggeffects)
<- lm(liking ~ rs_cat * partner_cat, data = reject_cat)
model_dev
ggemmeans(model_dev, terms=c("rs_cat")) %>% plot(add.data=TRUE, jitter=.2)
Plotting the main effect of partner’s emotional expression
## your code here
ggemmeans(model_dev, terms=c("partner_cat")) %>% plot(add.data=TRUE, jitter=.2)
Interaction
Plotting the interaction effect
## your code here
ggemmeans(model_dev, terms=c("rs_cat", "partner_cat")) %>% plot(add.data=TRUE, jitter=.2)
Switch how the interaction is visualized by switching the order of terms
## your code here
ggemmeans(model_dev, terms=c("partner_cat", "rs_cat")) %>% plot(show_data=TRUE, jitter=.2)
Question: How would you describe in a paper what the significant interaction effect means?
Simple effects
- Simple effects are the effect of some factor (e.g., interaction partner’s expression) at each level of another factor (e.g., at high and low RS separately).
Question: Does partner emotion have an effect on perceived liking for people low on rejection sensitivity? For people high on rejection sensitivty?
::emmeans(model_dev, pairwise~rs_cat*partner_cat) %>%
emmeansjoint_tests(by="rs_cat")
rs_cat = Low :
model term df1 df2 F.ratio p.value
partner_cat 1 76 3.134 0.0807
rs_cat = High :
model term df1 df2 F.ratio p.value
partner_cat 1 76 334.686 <.0001
Question: Does rejection sensitivity have an effect on perceived liking when partner shows neutral emotions? When partner shows happy emotions?
## your code here
::emmeans(model_dev, pairwise~rs_cat*partner_cat) %>%
emmeansjoint_tests(by="partner_cat")
partner_cat = Neutral :
model term df1 df2 F.ratio p.value
rs_cat 1 76 217.668 <.0001
partner_cat = Happy :
model term df1 df2 F.ratio p.value
rs_cat 1 76 3.134 0.0807
Reporting results
Write-up the results from the ANOVA analysis in APA style. Focus on one of the simple effect directions from above (they are equivalent so pick one that makes the most sense)
<- aov(model_dev)
aov_model report(aov_model)
The ANOVA (formula: liking ~ rs_cat * partner_cat) suggests that:
- The main effect of rs_cat is statistically significant and large (F(1, 76) =
84.28, p < .001; Eta2 (partial) = 0.53, 95% CI [0.40, 1.00])
- The main effect of partner_cat is statistically significant and large (F(1,
76) = 201.30, p < .001; Eta2 (partial) = 0.73, 95% CI [0.64, 1.00])
- The interaction between rs_cat and partner_cat is statistically significant
and large (F(1, 76) = 136.52, p < .001; Eta2 (partial) = 0.64, 95% CI [0.54,
1.00])
Effect sizes were labelled following Field's (2013) recommendations.