# Statistical test for n x m contingency tables

I have a dataset made up of elements from three groups, let's call them G1, G2, and G3. I analysed certain characteristics of these elements and divided them into 3 types of "behaviour" T1, T2, and T3 (I used cluster analysis to do that).

So, now I have a 3 x 3 contingency table like this with the counts of elements in the three groups divided by type:

      |    T1   |    T2   |    T3   |
------+---------+---------+---------+---
G1  |   18    |   15    |   65    |
------+---------+---------+---------+---
G2  |   20    |   10    |   70    |
------+---------+---------+---------+---
G3  |   15    |   55    |   30    |


Now, I can run a Fisher test on these data in R

data <- matrix(c(18, 20, 15, 15, 10, 55, 65, 70, 30), nrow=3)
fisher.test(data)


and I get

   Fisher's Exact Test for Count Data

data:  data
p-value = 9.028e-13
alternative hypothesis: two.sided


So my questions are:

• is it correct to use Fisher test this way?

• how do I know who is different from who? Is there a post-hoc test I can use? Looking at the data I would say the 3rd group has a different behaviour from the first two, how do I show that statistically?

• someone pointed me to logit models: are they a viable option for this type of analysis?

• any other option to analyse this type of data?

At first I think that the Fisher test is used correctly.

Count data are better handled using log-linear models (not logit, to ensure that the fitted values are bounded below). In R you can specify family=poisson (which sets errors = Poisson and link = log). The log link ensures that all the fitted values are positive, while the Poisson errors take account of the fact that the data are integer and have variances that are equal to their means. e.g. glm(y~x,poisson) and the model is fitted with a log link and Poisson errors (to account for the non-normality).

In cases where there is overdispersion (the residual deviance should be equal to the residual degrees of freedom, if the Poisson errors assumption is appropriate), instead of using quasipoisson as the error family, you could fit a negative binomial model. (This involves the function glm.nb from package MASS)

In your case you could fit and compare models using commands like the following:

observed <- as.vector(data)
Ts<-factor(rep(c("T1","T2","T3"),each=3))
Gs<-factor(rep(c("G1","G2","G3"),3))

model1<-glm(observed~Ts*Gs,poisson)

#or and a model without the interaction terms
model2<-glm(observed~Ts+Gs,poisson)

#you can compare the two models using anova with a chi-squared test
anova(model1,model2,test="Chi")
summary(model1)


Always make sure that your minimal model contains all the nuisance variables.

As for how do we know who is different from who, there are some plots that may help you. R function assocplot produces an association plot indicating deviations from independence of rows and columns in a two dimensional contingency table.

Here are the same data plotted as a mosaic plot

mosaicplot(data, shade = TRUE)

• Thank you, that's exactly what I needed. I'm not completely sure of what you mean when you talk about the overdispersion (sorry, I'm not a statistician, maybe it's something very basic)... You say that the residual deviance should be equal to the residual degrees of freedom... how would I check that?
– nico
Commented Jul 29, 2010 at 16:10
• If you give summary(model1) you'll see something like Residual deviance: -2.7768e-28 on 0 degrees of freedom Commented Jul 29, 2010 at 18:55

You can use multinom from nnet package for multinomial regression. Post-hoc tests you can use linearHypothesis from car package. You can conduct test of independence using linearHypothesis (Wald test) or anova (LR test).