13

I am modifying a graph built with ggplot by altering the data produced by ggplot_build (for a reason similar to Include space for missing factor level used in fill aesthetics in geom_boxplot). As far as I understand the help I found on this topic, I should be able to save the result by applying ggplot_gtable and arrangeGrob before calling ggsave on the results (Saving grid.arrange() plot to file).

However I obtain an error "plot should be a ggplot2 plot", also with this simple reproductible example:

require('ggplot2')
require('gridExtra')
df <- data.frame(f1=factor(rbinom(100, 1, 0.45), label=c("m","w")), 
                  f2=factor(rbinom(100, 1, 0.45), label=c("young","old")),
                  boxthis=rnorm(100))
g <- ggplot(aes(y = boxthis, x = f2, fill = f1), data = df) + geom_boxplot()
dd <- ggplot_build(g)

# Printing the graph works:
print(arrangeGrob(ggplot_gtable(dd)))

# Saving the graph doesn't:
ggsave('test.png',arrangeGrob(ggplot_gtable(dd)))

Can anybody explain why this does not work ? Is there a way to use ggsave after modifying the data by using ggplot_build() ?

(My version of the packages are gridExtra_0.9.1 and ggplot2_0.9.3.1)

Dave2e
  • 22,192
  • 18
  • 42
  • 50
Don't panic
  • 303
  • 1
  • 2
  • 10

2 Answers2

23

it does not work because ggsave wants an object of class ggplot, while you're passing a grob. arrangeGrob will sometimes trick ggsave in pretending inheritance from ggplot, but only when at least one of the grobs belongs to this class; here, however, you're only passing a gtable.

Perhaps the easiest workaround is to clone ggsave and bypass the class check,

ggsave <- ggplot2::ggsave; body(ggsave) <- body(ggplot2::ggsave)[-2]

Edit: The dev version of ggplot2 no longer requires this hack*, as ggsave now works with any grob.

*PS: this hack works no longer, as arrangeGrob now returns a gtable, and its print method does not draw on a device.

baptiste
  • 75,767
  • 19
  • 198
  • 294
  • 1
    Thanks. This, in combination with [link] (http://stackoverflow.com/a/20433318/2173340), fixed my problem of saving plots created by 'ggplot2' using 'gtable' with 'ggsave'. – Oskar Hansson Jan 20 '14 at 15:34
  • @baptiste I tried your trick with the overwriting `ggsave` function but it is not working in my case. At the same time, `ggplot` is still `1.0.1` and the problem is not fixed yet. If I use your method, I create a pdf file using `ggsave('test.pdf', arrangeGrob(p1, p2))` but it is corrupted in a way. At the same time the `gtable` get printed in the console. So something is not properly working. – drmariod Nov 19 '15 at 16:12
  • I just updated to gridExtra_2.0.0 and I have ggplot2_1.0.1 installed (which both seem to be the newest version on CRAN). As you state in your update `arrangeGrob` now returs a gtable, while `ggsave` still tests the class of the plot object. Do I have to install the development version of ggplot to save a plot done with arrangeGrob? – Latrunculia Dec 09 '15 at 21:17
  • Yes, note that a ggplot2 update is meant to be released soon, last time I checked last month – baptiste Dec 10 '15 at 05:18
1

A work around is to plot the gtable object with grid.draw() and then use dev.copy() to transfer the plot to a file.

Remember to use also dev.off() just afterward.

Bakaburg
  • 3,165
  • 4
  • 32
  • 64