Take the 2-minute tour ×
Cross Validated is a question and answer site for people interested in statistics, machine learning, data analysis, data mining, and data visualization. It's 100% free, no registration required.

I have read enough threads on QQplots here to understand that a QQplot can be more informative than other normality tests. However, I am inexperienced with interpreting QQplots. I googled a lot; I found a lot of graphs of non-normal QQplots, but no clear rules on how to interpret them, other than what it seems to be comparison with know distributions plus "gut feeling".

I would like to know if you have (or you know of) any rule of thumb to help you decide for non-normality.

This question came up when I saw these two graphs: graph 2 graph 1

I understand that the decision of non-normality depends on the data and what I want to do with them; however, my question is: generally, when do the observed departures from the straight line constitute enough evidence to make unreasonable the approximation of normality?

For what it's worth, the Shapiro-Wilk test failed to reject the hypothesis of non-normality in both cases.

share|improve this question
1  
the confidence bands around the QQ line are pretty cool. Can you share the R code you used to obtain them? –  user603 Aug 8 at 10:23
2  
It's just qqPlot() from {qualityTools} :) –  greymatter0 Aug 8 at 17:44

3 Answers 3

up vote 23 down vote accepted

Note that the Shapiro-Wilk is a powerful test of normality.

The best approach is really to have a good idea of how sensitive any procedure you want to use is to various kinds of non-normality (how badly non-normal does it have to be in that way for it to affect your inference more than you can accept).

An informal approach for looking at the plots would be to generate a number of data sets that are actually normal of the same sample size as the one you have - (for example, say 24 of them). Plot your real data among a grid of such plots (5x5 in the case of 24 random sets). If it's not especially unusual looking (the worst looking one, say), it's reasonably consistent with normality.

enter image description here

To my eye, data set "Z" in the center looks roughly on a par with "o" and "v" while "d" and "f" look slightly worse. "Z" is the real data. While I don't believe for a moment that it's actually normal, it's not particularly unusual when you compare it with normal data.

[Edit: I just conducted a random poll -- well, I asked my daughter, but at a fairly random time -- and her choice for the least like a straight line was "d". So 100% of those surveyed thought "d" was the most-odd one.]

More formal approach would be to do a Shapiro-Francia test (which is effectively based on the correlation in the QQ-plot), but (a) it's not even as powerful as the Shapiro Wilk test, and (b) formal testing answers a question (sometimes) that you should already know the answer to anyway (your data isn't exactly normal), instead of the question you need answered (how badly does that matter?).


As requested, code for the above display. Nothing fancy involved:

z = lm(dist~speed,cars)$residual
n = length(z)
xz = cbind(matrix(rnorm(12*n),nr=n),z,matrix(rnorm(12*n),nr=n))
colnames(xz) = c(letters[1:12],"Z",letters[13:24])

opar = par()
par(mfrow=c(5,5));
par(mar=c(0.5,0.5,0.5,0.5))
par(oma=c(1,1,1,1));

ytpos = (apply(xz,2,min)+3*apply(xz,2,max))/4
cn = colnames(xz)

for(i in 1:25) {
  qqnorm(xz[,i],axes=FALSE,ylab= colnames(xz)[i],xlab="",main="")
  qqline(xz[,i],col=2,lty=2)
  box("figure", col="darkgreen")
  text(-1.5,ytpos[i],cn[i])
}

par(opar)

Note that this was just for the purposes of illustration; I wanted a small data set that looked mildly non-normal which is why I used the residuals from a linear regression on the cars data (the model isn't quite appropriate). However, if I was actually generating such a display for a set of residuals for a regression, I'd regress all 25 data sets on the same $x$'s as in the model, and display QQ plots of their residuals, since residuals have some structure not present in normal random numbers.

share|improve this answer
3  
+1. I really like the idea to compare the QQ-plots of your sample with some randomly generated ones! –  COOLSerdash Aug 7 at 15:22
    
Thank you @Glen_b. Can I ask you how did you produce the grid of graphs? –  greymatter0 Aug 9 at 12:33
1  
I just discovered I never responded to your request, greymatter0. There's not really room, to put my whole script, but I'll outline the gist of it. I played with plot options -- opar=par(); par(mfrow=c(5,5)); par(mar=c(0.5,0.5,0.5,0.5)); par(oma=c(1,1,1,1)) then in a loop over i I did qqnorm(xz[,i],axes=FALSE,ylab= colnames(xz)[i],xlab="",main=""); qqline(xz[,i],col=2,lty=2); box("figure", col="darkgreen") then at the end par(opar) to set the options back to whatever they were before. That leaves out some of the details but you should be able to manage from there. –  Glen_b Sep 8 at 9:56
    
@greymatter0 ... and now I discover I didn't properly ping you before when I did finally answer. My apologies. –  Glen_b Oct 8 at 1:14
    
Don't worry Glen_b, thank you so much for remembering! –  greymatter0 Oct 8 at 6:14

Like @Glen_b said, you can compare your data with the data you're sure is normal - the data you generated yourself, and then rely on your gut feeling :)

The following is an example from OpenIntro Statistics textbook

Let's have a look at this Q-Q Plot:

qq1

Is it normal? Let's compare it with normally distributed data:

qq2

This one looks better than our data, so our data doesn't seem normal. Let's make sure by simulating it several times and plotting side-by-side

qq3

So our gut feeling tells us that the sample is not likely to be distributed normally.

Here's the R code to do this

load(url("http://www.openintro.org/stat/data/bdims.RData"))
fdims = subset(bdims, bdims$sex == 0)

qqnorm(fdims$wgt, col=adjustcolor("orange", 0.4), pch=19)
    qqline(fdims$wgt)

qqnormsim = function(dat, dim=c(2,2)) {
  par(mfrow=dim)
  qqnorm(dat, col=adjustcolor("orange", 0.4), 
         pch=19, cex=0.7, main="Normal QQ Plot (Data)")
  qqline(dat)
  for (i in 1:(prod(dim) - 1)) {
    simnorm = rnorm(n=length(dat), mean=mean(dat), sd=sd(dat))
    qqnorm(simnorm, col=adjustcolor("orange", 0.4), 
           pch=19, cex=0.7,
           main="Normal QQ Plot (Sim)")
    qqline(simnorm)
  }
  par(mfrow=c(1, 1))
}
qqnormsim(fdims$wgt)
share|improve this answer

There are many tests of normality. One usually focuses on the null hypothesis, namely, "$H_0: F=Normal$". However, little attention is paid to the alternative hypothesis: "against what"?

Typically, tests that consider any other distribution as the alternative hypothesis have low power when compared against tests with the right alternative hypothesis (see, for instance, 1 and 2).

There is an interesting R package with the implementation of several nonparametric normality tests ('nortest', http://cran.r-project.org/web/packages/nortest/index.html). As mentioned in the papers above, the likelihood ratio test, with appropriate alternative hypothesis, is more powerful than these tests.

The idea mentioned by @Glen_b about comparing your sample against random samples from your (fitted) model is mentioned in my second reference. They are called "QQ-Envelopes" or "QQ-Fans". This implicitly requires having a model to generate the data from and, consequently, an alternative hypothesis.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.