# How to perform a 4 by 4 mixed ANOVA with between- and within-subjects contrasts using R?

Beginner user of R here struggling with a repeated measures ANOVA.

I have a dataset that consists of one between subjects factor with 4 levels (coded in a single variable called 'groups'), and one within subjects factor with 4 levels (coded in four separate variables 'DV1', 'DV2', 'DV3', 'DV4').

I have the following objectives:

1. Run an overall repeated measures ANOVA.
2. Compare groups using custom contrasts (as in an LMATRIX command in SPSS).
3. Compare different levels of DV using custom contrasts (as in an MMATRIX command in SPSS).
4. Do a combination of 2) and 3) simultaneously so I am comparing only certain groups at certain levels of the within-subjects factor.
5. Run a set of contrasts that do NOT sum to zero.

I know I can do this in SPSS without much of a problem, but I can't get a clear idea of how to do this in R. I've seen how parts of this could work in different packages, but I have not so far seen how this could work within one procedure or a set of related procedures in R.

-
add comment

## 1 Answer

I am currently writing on a blog post for the CrossValidated community blog that talks about nothing but this problem. I will update this answer with a link to this post when it is done (hopefully this week).

So long, I will sketch the solution:

1. Data needs to be in the long format (i.e., on value per row) instead of in the wide format as in SPSS (i.e., one subject per row), see the reshape package, or ?reshape. That includes that there needs to be a variable indicating the subject identifier (i.e., subject id).
2. All factors (including the subject identifier) must be of class factor (run str on your data frame to check this). If you don't do this your results will be wrong.
3. If you want to obtain type-III sums of squares set the default contrasts to effect coding:
options(contrasts=c("contr.sum","contr.poly"))
4. Specify the desired model with lme from the nlme package (install and load the package beforehands via install.packages("nlme") and library(nlme)) using a compund symmetric correlation structure. See the answer and especially my comment to the accepted answer to this question. In your case that could be something like (if you would have provided sample data, which is strongly recommended, you would have received the correct code):
my.anova <- lme(dv ~ group*within, data = your.df, random = ~1|id, correlation = corCompSymm(form = ~1|id))
5. Use the generic anova function to obtain the anova table (see ?anova.lme):
anova(my.anova)
To obtain type-III sums of squares use the anova command with argument type set to "marginal" (this only works if contrasts are set to effects coding, see point 3):
anova(my.anova, type = "marginal")
6. The fitted object of type lme now allows diverse functions to perform contrasts. The most flexible solution (but a rather unhandy one) is the L argument in a call to anova.lme (see again ?anova.lme).
Other solutions also require a fitted lme object as an argument:
Also very flexible is the estimable function from the gmodels package. This package also offers the fit.contrasts function.
The multcomp package allows contrasts using alpha-error adjustment (but you can only perform contrasts using one of your factors), using the glht function.
A new and promising approach is the contrast package, however, so far it does not seem to privde all possible contrasts.
-
(+1) Great and very instructive response. Waiting for the blog post... –  chl Sep 14 '11 at 10:49
?anova.lme doesn't work for me and methods(anova) lists it as a non-visible function. –  John Sep 14 '11 at 12:04
@John Did you load nlme before? If not, run library(nlme), then it should work. If it is still not working, install.packages("nlme") first. –  Henrik Sep 14 '11 at 12:06
ah... I hadn't apparently, only lme4 –  John Sep 14 '11 at 13:13
Thanks, I'll try this out. –  aquadhere Sep 15 '11 at 2:19
show 4 more comments