ezMixed provides an interface to fitting/evaluating mixed effects models (a.k.a. hierarchical models), which are different from mixed anovas. They are generally superior to anova and permit missing data. It's a little involved to explain precisely how they achieve inference amidst missing data, but if you should be able to find explanations if you search "mixed effects models and missing data".
Below is how you'd go about using ezMixed. Note that when you have a variable like Time that you've turned into a 7-level factor, the first model will treat that variable categorically (i.e. it doesn't "see" the ordering of levels nor their equal spacing), which generally has the risk of losing power to detect linear effects. The code below shows how to run a second version of the analysis that treats Time properly as a continuous variable, employing generalized additive modelling to estimate a possibly-non-linear function. It actually ends up deciding for your case that a linear function fits best, but behind the scenes it tries a bunch of wiggly functions, so you should trust that the linear is the best prediction.
#load libraries
library(lme4)
library(mgcv)
library(ez)
library(ggplot2)
#make sure "Group" has sum contrasts
contrasts(mixed_anova_data$Group) = contr.sum
#make sure "Time" has helmert contrasts
contrasts(mixed_anova_data$Time) = contr.helmert
#fit mixed effects models, obtaining likelihood ratios for each fixed effect
# note: since "Time" is a factor, it is treated as a categorical variable
fit = ezMixed(
data = mixed_anova_data[!
is.na(mixed_anova_data$PERCLOS.value),]
, dv=.(PERCLOS.value)
, random=.(Participant)
, fixed=.(Time,Group)
)
#get posterior predictions from the maximal model
preds = ezPredict(fit$models$`Group:Time`$unrestricted)
#plot all groups
ezPlot2(
preds = preds
, x = Time
, split = Group
)
#plot group differences
ezPlot2(
preds = preds
, x = Time
, diff = Group
)
#Turn "Time" into a number to run a GAMM
mixed_anova_data$Time2 = as.numeric(as.character(mixed_anova_data$Time))
#fits generally converge better and posterior plots look nicer if numeric variables are scaled
mixed_anova_data$Time3 = scale(mixed_anova_data$Time2)
#fit mixed effects models, obtaining likelihood ratios for each fixed effect
# note: since "Time3" is a number, a generalized additive mixed model will be fit
fit2 = ezMixed(
data = mixed_anova_data[!
is.na(mixed_anova_data$PERCLOS.value),]
, dv=.(PERCLOS.value)
, random=.(Participant)
, fixed=.(Time3,Group)
)
#get posterior predictions from the maximal model
preds2 = ezPredict(fit2$models$`Group:Time3`$unrestricted)
#unscale Time
preds2$cells$Time = preds2$cells$Time3*sd(mixed_anova_data$Time2)+mean(mixed_anova_data$Time2)
preds2$boots$Time = preds2$boots$Time3*sd(mixed_anova_data$Time2)+mean(mixed_anova_data$Time2)
#plot all groups
ezPlot2(
preds = preds2
, x = Time
, split = Group
)
#plot group differences
ezPlot2(
preds = preds2
, x = Time
, diff = Group
)
#Estimate a truly "maximal" mixed effects model by hand
# Note: this treats time as having LINEAR effects
fit3 = lmer(
data = mixed_anova_data[!
is.na(mixed_anova_data$PERCLOS.value),]
, formula = PERCLOS.value ~ Time3*Group + (1+Time3*Group|Participant)
)
#get posterior predictions from the maximal model
preds3 = ezPredict(fit3)
#unscale Time
preds3$cells$Time = preds3$cells$Time3*sd(mixed_anova_data$Time2)+mean(mixed_anova_data$Time2)
preds3$boots$Time = preds3$boots$Time3*sd(mixed_anova_data$Time2)+mean(mixed_anova_data$Time2)
#plot all groups
ezPlot2(
preds = preds3
, x = Time
, split = Group
)
#plot group differences
ezPlot2(
preds = preds3
, x = Time
, diff = Group
)