3

Some test data:

ltd <- data.frame(r = c(rnorm(10), f1 = c(rep("L", 5), rep("H", 5)),
       f2 = rep(c("A", "B"), 5))

And a minimal function:

tf <- function(formula = NULL, data = NULL) {

res <- as.character(formula[[2]]) # clean & prep data
fac1 <- as.character(formula[[3]][2])
fac2 <- as.character(formula[[3]][3])

counts <- count(data, vars = c(fac2, fac1)) # get table data ready
colnames(counts) <- c(fac2, fac1, "count")
myt <- tableGrob(counts, show.box = TRUE,
    show.rownames = FALSE, show.colnames = TRUE,
    show.csep = TRUE, show.rsep = TRUE,
    separator = "black")

p <- ggplot()
p <- p + geom_point(data = data, 
    aes_string(x = fac1, y = res, color = fac2, group = fac2))      
p <- p + annotation_custom(myt) # comment out and it works
}

Run it:

require("plyr")
require("gridExtra")
require("ggplot2")
tmp <- tf(formula = r~f1*f2, data = ltd)
print(tmp)

Gives Error in if (nrow(layer_data) == 0) return() : argument is of length zero

If you print the tableGrob it does exist, so I'm not sure what's going on here. If you comment out the annotation_custom it works, and I think I'm following the docs. Thanks. (ggplot2_0.9.3)

Bryan Hanson
  • 6,055
  • 4
  • 41
  • 78
  • my guess is that `annotation_custom` doesn't like discrete axes (like `annotation_raster`). You would need to specify xmin,xmax,ymin,ymax, in any case, but it still doesn't work here. – baptiste Jan 18 '13 at 03:02
  • It's OK with discrete axes, I had it working in another version. But I was making some changes to use a simple formula interface and comply with the latest changes in ggplot2 and it broke. – Bryan Hanson Jan 18 '13 at 03:06

1 Answers1

3

Here is solution to your problem: I relocated your data= and aes_string call to the main ggplot call. I don't know why it matters, but now the plot prints without error.

p <- ggplot(data=data, aes_string(x=fac1, y=res, color=fac2, group=fac2)) + 
     geom_point() +
     annotation_custom(myt)

enter image description here

bdemarest
  • 14,397
  • 3
  • 53
  • 56
  • Nice catch :) In the function, myt was computed from counts, which in turn was computed from data using variables fac1 and fac2. Your fix placed the aesthetics fac1 and fac2 in the base layer, so those aesthetics could be referenced in the annotation_raster layer, although it's interesting to me that it works since myt is generated from the counts data frame rather than data. As Bryan quipped in another post, 'each layer needs data and aesthetics' :) But in all fairness, the error is rather subtle... – Dennis Jan 18 '13 at 09:42
  • @Dennis @bdemarest Thanks. I'm quite puzzled with the fix, but it does work. I'm not sure if I can use this solution in the full function (which I didn't provide), but I'll try. In the full function, I was taking great pains to keep all the layers completely separate as there was cross talk between the aesthetics. Hence the simple `ggplot()` to intialiize the whole process w/o default aesthetics. And I was really trying to keep to the (data, aesthetic, geom)/each layer, but `annotation_custom` doesn't really conform to that (but maybe the problem is that it *does* under the hood). – Bryan Hanson Jan 18 '13 at 12:49
  • @BryanHanson This looks like a bug to me. Your code is legal. Is this the same problem as https://github.com/hadley/ggplot2/issues/756? – Faheem Mitha May 13 '13 at 08:26