As both a stats and R novice, I have been having a really difficult time trying to generate qqplots with an aspect ratio of 1:1. ggplot2 seems to offer far more control over plotting than the default R plotting packages, but I can't see how to do a qqplot in ggplot2 to compare two datasets.

So my question, what is the ggplot2 equivalent of something like:


The easiest thing to do is just look at how qqplot works. So in R type:

R> qqplot
function (x, y, plot.it = TRUE, xlab = deparse(substitute(x)), 
    ylab = deparse(substitute(y)), ...) 
    sx <- sort(x)
    sy <- sort(y)
    lenx <- length(sx)
    leny <- length(sy)
    if (leny < lenx) 
        sx <- approx(1L:lenx, sx, n = leny)$y
    if (leny > lenx) 
        sy <- approx(1L:leny, sy, n = lenx)$y
    if (plot.it) 
        plot(sx, sy, xlab = xlab, ylab = ylab, ...)
    invisible(list(x = sx, y = sy))
<environment: namespace:stats>

So to generate the plot we just have to get sx and sy, i.e:

x <- rnorm(10);y <- rnorm(20)

sx <- sort(x); sy <- sort(y)
lenx <- length(sx)
leny <- length(sy)
if (leny < lenx)sx <- approx(1L:lenx, sx, n = leny)$y
if (leny > lenx)sy <- approx(1L:leny, sy, n = lenx)$y

g = ggplot() + geom_point(aes(x=sx, y=sy))

qqplot using ggplot2

  • 2
    $\begingroup$ ggplot2 does have a stat_qq(), is there some way to use that? It seems to be designed to compare one vector to a theoretical distribution, I couldn't see how to use it to compare two different vectors. $\endgroup$ – Ken Williams Apr 20 '12 at 15:37
  • 7
    $\begingroup$ You can actually get qqplot() to do all the sort/length/approx calculations for you: d <- as.data.frame(qqplot(x, y, plot.it=FALSE)); ggplot(d) + geom_point(aes(x=x, y=y)) $\endgroup$ – Ken Williams Apr 20 '12 at 16:04

I use this when I also want a normal line.

ggplot(data, aes(sample = data$column1)) + stat_qq(color="firebrick2", alpha=1) + geom_abline(intercept = mean(data$column1), slope = sd(data$column1))


If your original need is just to control the aspect ratio, here's one way to do that:

x <- rnorm(1000)
y <- rnorm(1500, 2)

myqq <- function(x, y, ...) {
  rg <- range(x, y, na.rm=T)
  qqplot(x, y, xlim=rg, ylim=rg, ...)

myqq(x, y)

myqq plot


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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