Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

inheritance of aesthetics in ggplot2 0.9.3 & the behavior of annotation_custom

Tags:

r

ggplot2

Following up on a recent question of mine, this one is a bit different and illustrates the problem more fully using simpler examples. Below are two data sets and three functions. The first one draws some points and a circle as expected:

library("ggplot2")
library("grid")

td1 <- data.frame(x = rnorm(10), y = rnorm(10))

tf1 <- function(df) { # works as expected
    p <- ggplot(aes(x = x, y = y), data = df)
    p <- p + geom_point(color = "red")
    p <- p + annotation_custom(circleGrob())
    print(p)
}

tf1(td1)

This next one seems to ask for the exact sample plot but the code is slightly different. It does not give an error but does not draw the circle:

tf2 <- function(df) { # circle isn't draw, but no error either
    p <- ggplot()
    p <- p + geom_point(data = df, aes(x = x, y = y), color = "red")        
    p <- p + annotation_custom(circleGrob())
    print(p)
    }

tf2(td1)

Finally, this one involves a more complex aesthetic and gives an empty layer when you try to create the circle:

td3 <- data.frame(r = c(rnorm(5, 5, 1.5), rnorm(5, 8, 2)),
    f1 = c(rep("L", 5), rep("H", 5)), f2 = rep(c("A", "B"), 5))

tf3 <- function(df) {
    p <- ggplot()
    p <- p + geom_point(data = df, 
        aes(x = f1, y = r, color = f2, group = f2))     
#   p <- p + annotation_custom(circleGrob()) # comment out and it works
    print(p)
    }

tf3(td3)

Now, I suspect the problem here is not the code but my failure to grasp the inner workings of ggplot2. I could sure use an explanation of why the circle is not drawn in the 2nd case and why the layer is empty in the third case. I looked at the code for annotation_custom and it has a hard-wired inherit.aes = TRUE which I think is the problem. I don't see why this function needs any aesthetic at all (see the docs on it). I did try several ways to override it and set inherit.aes = FALSE but I was unable to fully penetrate the namespace and make it stick. I tried to example the objects created by ggplot2 but these proto objects are nested very deeply and hard to decipher.

like image 997
Bryan Hanson Avatar asked Jan 19 '13 13:01

Bryan Hanson


1 Answers

To answer this :

"I don't see why this function needs any aesthetic at all".

In fact annotation_custom need x and y aes to scale its grob, and to use after the native units. Basically it did this :

  x_rng <- range(df$x, na.rm = TRUE)                            ## ranges of x :aes x
  y_rng <- range(df$y, na.rm = TRUE)                            ## ranges of y :aes y
  vp <- viewport(x = mean(x_rng), y = mean(y_rng),              ##  create a viewport
                 width = diff(x_rng), height = diff(y_rng),
                 just = c("center","center"))
  dd <- editGrob(grod =circleGrob(), vp = vp)                  ##plot the grob in this vp 

To illustrate this I add a grob to a dummy plot used as a scale for my grob. The first is a big scale and the second is a small one.

base.big   <- ggplot(aes(x = x1, y = y1), data = data.frame(x1=1:100,y1=1:100))
base.small <- ggplot(aes(x = x1, y = y1), data = data.frame(x1=1:20,y1=1:1))

I define my grob, see I use the native scales for xmin,xmax,ymin,ymax

annot <- annotation_custom(grob = circleGrob(),  xmin = 0, 
                                                 xmax = 20, 
                                                 ymin = 0, 
                                                 ymax = 1)

Now see the scales difference(small point / big circle) between (base.big +annot) and (base.small + annot).

library(gridExtra)
grid.arrange(base.big+annot,
             base.small+annot)

enter image description here

like image 61
agstudy Avatar answered Oct 12 '22 23:10

agstudy