# ANOVA comparison between genders controlling for additional factor

I am interested in finding out exam results differ between gender, controlling for the school the students attended. For now i have done ANOVA comparison of exam results. There are significant differences, according to ANOVA test.

How can I control for the school?

There are only three different schools. I am doing the analysis in R. Unfortunately, I am not allowed to post my data. The amount of respondents in each group in not the same.

Would two way ANOVA with unequal sample sizes be suitable ?

Yes, that would be appropriate. You can run a two way ANOVA as follows (using the built in mtcars data set as an example).

summary(aov(mpg ~ cyl + gear, data = mtcars))


which yields ...

            Df Sum Sq Mean Sq F value   Pr(>F)
cyl          1  817.7   817.7   78.29 9.82e-10 ***
gear         1    5.4     5.4    0.52    0.477
Residuals   29  302.9    10.4
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1


In addition, if you just wanted to compare two specific groups, you could us a t-test. Something like this would work.

# Create sample dataframe
df <- data.frame(
SchoolA_males = round(runif(10, 50, 100),0),
SchoolA_females = round(runif(10, 50, 100),0),
SchoolB_males = round(runif(10, 50, 100),0),
SchoolB_females = round(runif(10, 50, 100),0),
SchoolC_males = round(runif(10, 50, 100),0),
SchoolC_females = round(runif(10, 50, 100),0)
)
# Run a t-test
t.test(df$SchoolA_males, df$SchoolA_females)

# And don't forget some nifty box plots!
boxplot(df)


It really depends on your scenario, which there's very minimal information on. If you do end up running the ANOVA, make sure you use type III SS; as these tests are not reliant on cell size or order of parameters. I am not quite sure how to get type III for the individual parameters without manual multiplication by contrast (will add example within a day or 2), but you can use this for the overall model:

options(contrasts=c("contr.sum", "contr.poly"))

### Dummy up data -----
set.seed(123)

df <- mapply(
function(ns, mns, sds){ rnorm(ns,mns,sds) },
ns = c(19, 20, 19, 23, 20, 19), # n
mns = c(80, 82, 77, 83, 88, 75), # mean
sds = c(5, 4, 4, 3, 7, 3) # sd
)
names(df) <- c('Male_A', 'Male_B', 'Male_C', 'Female_A', 'Female_B', 'Female_C')

df <- stack(df)

### Construct orthogonal contrasts -----
con1 <- c(-1, -1, -1, 1, 1, 1) # Male vs. Female
con2 <- c(2, -1, -1, 0, 0, 0) # Male school A vs Male schools B & C
con3 <- c(0, 1, -1, 0, 0, 0) # Male school B vs Male school C
con4 <- c(0, 0, 0, 2, -1, -1) # Female school A vs. Female schools B & C
con5 <- c(0, 0, 0, 0, 1, -1) # Female school B vs. Female school C

conts <- cbind(con1, con2, con3, con4, con5)

### Model -----
mod1 <- lm(values ~ ind, data = df,
contrasts = list(ind = conts))
summary(mod1)

Anova(mod1, type = '3')


Once the type III SS is used, the first contrast code will represent the distance between males and females over and above the "effect of school".