File Exchange

image thumbnail

Two-way repeated measures ANOVA

version (2.72 KB) by Aaron Schurger
Two-way repeated measures ANOVA, for designs with two within-subjects variables.


Updated 24 Jul 2011

View License

% function stats = rm_anova2(Y,S,F1,F2,FACTNAMES)
% Two-factor, within-subject repeated measures ANOVA.
% For designs with two within-subject factors.
% Parameters:
% Y dependent variable (numeric) in a column vector
% S grouping variable for SUBJECT
% F1 grouping variable for factor #1
% F2 grouping variable for factor #2
% FACTNAMES a cell array w/ two char arrays: {'factor1', 'factor2'}
% Y should be a 1-d column vector with all of your data (numeric).
% The grouping variables should also be 1-d numeric, each with same
% length as Y. Each entry in each of the grouping vectors indicates the
% level # (or subject #) of the corresponding entry in Y.
% Returns:
% stats is a cell array with the usual ANOVA table:
% Source / ss / df / ms / F / p
% Notes:
% Program does not do any input validation, so it is up to you to make
% sure that you have passed in the parameters in the correct form:
% Y, S, F1, and F2 must be numeric vectors all of the same length.
% There must be at least one value in Y for each possible combination
% of S, F1, and F2 (i.e. there must be at least one measurement per
% subject per condition).
% If there is more than one measurement per subject X condition, then
% the program will take the mean of those measurements.
% Aaron Schurger (2005.02.04)
% Derived from Keppel & Wickens (2004) "Design and Analysis" ch. 18

Comments and Ratings (42)

There seems to be some sort of major flaw in the code. No matter what data I input, I only get nans out. Based on previous comments, it looks like the code used to work, so my guess is that an error was introduced in a patch that results in the data not being indexed appropriately and only nans to come out the other end. I've tried using this function on real and made up data. I've tried modifying how the data was input. I've tried stopping the code and following it at every point through the code. It always ends in nans and as far as I can tell, it seems to be an indexing issue. Hopefully this issue is resolved soon. This is exactly the kind of function I need for my data. But until it is fixed, I cannot use it.

Xiuyun Wu

Danlei Chen

Here are the edits I made to include generalized eta squared into the script (starting at line 136):

n2gA = ssA / (ssA + ssS + ssAS + ssBS + ssABS);
n2gB = ssB / (ssB + ssS + ssAS + ssBS + ssABS);
n2gAB = ssAB / (ssAB + ssS + ssAS + ssBS + ssABS);

% return values
stats = {'Source','SS','df','MS','F','p','n2g';...
FACTNAMES{1}, ssA, dfA, msA, fA, pA, n2gA;...
FACTNAMES{2}, ssB, dfB, msB, fB, pB, n2gB;...
[FACTNAMES{1} ' x ' FACTNAMES{2}], ssAB, dfAB, msAB, fAB, pAB, n2gAB;...
[FACTNAMES{1} ' x Subj'], ssAS, dfAS, msAS, [], [], [];...
[FACTNAMES{2} ' x Subj'], ssBS, dfBS, msBS, [], [], [];...
[FACTNAMES{1} ' x ' FACTNAMES{2} ' x Subj'], ssABS, dfABS, msABS, [], [], [];...
'Subjects', ssS, dfS, msS, [], [], []};


Arsene Ella

Hi Aaron
I've got NaN output for example data of the matlab anova2.....

load popcorn

popcorn (Y = Data)

5.5000 4.5000 3.5000
5.5000 4.5000 4.0000
6.0000 4.0000 3.0000
6.5000 5.0000 4.0000
7.0000 5.5000 5.0000
7.0000 5.0000 4.5000

This example is could be designed like this with your code:

S (Subjects or Different measures)

1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6

F1 (Brand Factor (Gourmet =1, National =2, Genneric = 3) )

1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3

F2 (Popper factor (OIL=1, AIR=2) )

1 1 1
1 1 1
1 1 1
2 2 2
2 2 2
2 2 2

Setting everything in 1-d column vectors

Y S F1 F2
5.5 1 1 1
5.5 2 1 1
6.0 3 1 1
6.5 4 1 2
7.0 5 1 2
7.0 6 1 2
4.5 1 2 1
4.5 2 2 1
4.0 3 2 1
5.0 4 2 2
5.5 5 2 2
5.0 6 2 2
3.5 1 3 1
4.0 2 3 1
3.0 3 3 1
4.0 4 3 2
5.0 5 3 2
4.5 6 3 2

Setting the FACTNAMES cell array:

BRAND = {'Gour', 'Nati', 'Gene'}
POPPER = {'Oil', 'Air'}

Launching the program:
stats = rm_anova2(Y,S,F1,F2,FACTNAMES)

I've got this result:

stats =

'Source' 'SS' 'df' 'MS' 'F' 'p'
{1x3 cell} [NaN] [ 2] [NaN] [NaN] [NaN]
{1x2 cell} [NaN] [ 1] [NaN] [NaN] [NaN]
{1x6 cell} [NaN] [ 2] [NaN] [NaN] [NaN]
{1x4 cell} [NaN] [10] [NaN] [] []
{1x3 cell} [NaN] [ 5] [NaN] [] []
{1x7 cell} [NaN] [10] [NaN] [] []


I get NaN output for perfectly ok data....

It's a super useful and great piece of code!
A big thanks to Aaron Schurger!


Hi all, I have recently used this code to run rmANOVA. It is great. I have a question regarding the writing up the result. Since the code only gives Source / ss / df / ms / F / p values I am not sure how to report this. Is there an updated version which also includes the error?
Here is what I got:
'Source' 'SS' 'df' 'MS' 'F' 'p'
'Factor1' [ 2.4939] [ 2] [ 1.2469] [16.8086] [5.8960e-06]
'Factor2' [305.1127] [ 9] [33.9014] [59.9041] [ 0]
'Factor1 x Factor2' [ 15.7699] [ 18] [ 0.8761] [11.9694] [ 0]
'Factor1 x Subj' [ 2.8190] [ 38] [ 0.0742] [] []
'Factor2 x Subj' [ 96.7737] [171] [ 0.5659] [] []
'Factor1 x Factor2 x Subj' [ 25.0327] [342] [ 0.0732] [] []

Is there any way to get the error calculated also to get "[] or [0]" as a value?
I will appreciate your help!
Thanks in advance.

Yueqi Ren

What does the other p-values (corresponding to FACTNAMES{1} and to FACTNAMES{2}, respectively) mean? I'm don't quite follow the procedure you use to find those p-values. Any clarification is appreciated!


Aaron, how do we estimate the effect size here. Usually eta2 is used for effect size = SSeffect / SStotal.
In case of an example that I ran with repeated measures, 2 factors each with 2 levels and 1 response variable, I got the 'source' in the table as:
factor 1, factor 2, factor 1 x factor 2, factor 1 x subjects , factor 2 x subjects, factor 1 x factor 2 x subjects. I am not sure if the SStotal the sum of all of these..? Can you please confirm.

Echo M

Thank you for the script, Aaron. will this script work for unbalanced samples (i.e. different number of subjects
per group) ?

K Jay

Can we include between-subject factors here?

Hi all,

It's not clear to me how input data (Y, S, F1,F2, FACTNAMES) have to be arranged. Can someone gives an example? Thanks!

I am not sure what to put for the FACTNAMES. I have entered "1"s and "2"s for the conditions in F1 & F2 is this correct?


Solved it!


Is the result of p-value from first line indicating the result of within subject?

Hi, Marc,
This procedure is strictly for situations where you have exactly two within-subjects factors. To my knowledge there exists no n-factor repeated measures ANOVA algorithm. Just going from two-factor to three-factor you have a huge jump in complexity of the algorithm, and when you have different numbers of between-subjects and within-subjects factors things get really scary really fast. But there are functions on the File Exchange for more than two factors.


Will this file work for a multi-factor (more than two factors) ANOVA?

Will it also work on a One-Way ANOVA?


This seems very promising, but I can't figure out what kind of input is needed. For instance, what is d in the function definitions, and are Y and grouping vectors meant to comprise one column or multiple columns? It would be very helpful if the author could include with his download a small .mat file with sample inputs for Y, F1, F2 etc.


the script works now - I appear to have had an old version of the script.


Good submission. I found this script gives the same results as anovan. To do repeated measures with anovan, its necessary to make another factor for subjects, and specify that factor as 'random'.

for the data that made me spot the bug the script displays the following first three lines of the ANOVA tables.

If you take the average from multiple cells by hand:

'Source'SS df MS F p
'cond' 1.0413 1 1.0413 1.8483 0.1971
'hand' 0.2325 1 0.2325 1.7135 0.2132
'cxh' 0.1184 1 0.1184 2.7210 0.1230

if you enter several values for multiple cells, according to documentation, it should do the same thing automatically, but doesn't:

Source SS df MS F p
'cond' 1.0413 1 1.0413 1.8483 0.1971
'hand' 0.2325 1 0.2325 1.7135 0.2132
cdxhd 0.1184 1 0.1184 1.4417e-05 0.9970

which is jsut plainly wrong (note that first 3 columns are identical). i would be surprised if Statistica did the same. i did the calculations by hand at the time to figure out what exactly went wrong but cannot remember - if you're interested in the data please be in touch.


Thanks a lot.

I precise I just needed to change :




and it works great ! (same results as Statistica)


I agree this is a very well written script. However, I am somewhat confused about the Y input variable. In the comments above it says that 'Y' should be a column vector (I assume this means (:, 1)). My confusion comes from the following lines:

for i=1:a % F1
for j=1:b % F2
for k=1:n % Subjs
INDS{i,j,k} = ...
CELLS{i,j,k} = Y(INDS{i,j,k});
MEANS(i,j,k) = mean(CELLS{i,j,k});

The '...' was placed instead of the code to create the indices. The line CELLS{i,j,k} = Y(INDS{i,j,k}); generates a 3D cell from Y, which makes sense to have the data in three dimensions, however Y is a 1D column and creates a large number of NaNs.

Also, Matlab produces the following error:

??? Error using ==> horzcat
CAT arguments dimensions are not consistent.

Error in ==> rm_anova2 at 138
stats = {'Source','SS','df','MS','F','p';...

Long story short, what am I not getting about this?

There's a mistake in this script: if several measurements are provided for one cell, it gives wrong values for the interaction. help says it would take the average in that case, which it does for the most part, but at some point it gets confused with the number of measurements taken and F and p are then really wrong (only concerns interaction with several values per cell).

By the way, RMAOV2 --> same functionality, even though a bit bulky, takes the variance across repeated measurements for the same cell into consideration.

Alberich Qi

I think it should be written as :

FACTNAMES = {F1name, F2name};
F1name = {'abc' , ..., 'xyz'};
F2name = {'xx', ..., 'yy'};

It can work well in my script.


I would also appreciate a one line example of how to enter FACTNAMES. I'm getting an error. Thanks!



Can someone give me a one line example of how to enter FACTNAMES? I'd appreciate it.

Hi, Zachary,
Good question. No, it was not designed to deal with a different number of subjects on each factor. Sorry about that. It might not be too complicated to code, but I imagine that there are some statistical issues to be mindful of, and I would want to look into that before changing the code. In the meantime, you might be able to insert a dummy value, which is just the mean of the other values, just to make the program work. One thing that I can do is to make the program generate an error instead of just giving back nan's. It would help to see the data, just as you passed them to the program. -Aaron

The stats output is a cell array of NaNs. Is this software capable of dealing with unequally distributed data? I.e., 7 subjects are evaluated on factor 1, but only 6 are evaluated on factor 2.

piyush singhal

terence hill

keidit chankhachon

Perspicacity Slim

It would make my day if you could add Greenhouse-Geiser correction for violating the sphericity assumption of repeated measures ANVOA.

Ashwin Sundar

malia mason

This worked well for me.

adam mcnamara

Examples with data are always very helpful.. this is what this lacks

Teck Por Lim

The author had corrected the code after Ted Zanto's comment in 2005.

dojoon yi

It is great. Thank you!!!

Ted Zanto

Excellent program...does exactly what it's designed for. Easy to implement and coded in a very straightforward manner. Results were confirmed in SPSS...right on the mark.

One tiny error on line 133: FACTNAMES{1} should be FACTNAMES{2}...but this merely a labeling issue.

Nonetheless, it's a great program, thanks Aaron!

Aaron Schurger

A very well-written program (of course, I wrote it myself). One or two additional features are of interest, so I would not yet call it excellent.


Fixed one minor error in the labeling of the output, and also modified the comments.

Fixed a minor error in the code. Uploaded new version. I had fixed this problem quite a while back, and uploaded the file. It may not have uploaded properly the first time. Thanks to Johan Carlin for bringing the problem to my attention.

Reviewer Ted Zanto ( noticed a minor error on line 133: FACTNAMES{1} should be FACTNAMES{2}. Corrected this error. This error would have been of little or no consequence to users of the program.

There was a minor problem in the code (line 70) which would produce inaccurate results if you did not average your data within each condition prior to calling the function. This is now fixed.

An error on line 70 of the code produced errors if you ran the ANOVA on your raw data, without having previously averaged the measurements within each cell. This feature now works correctly.

MATLAB Release Compatibility
Created with R13SP1
Compatible with any release
Platform Compatibility
Windows macOS Linux