37

I have a function that does stuff and then plots based on a condition:

f <- function(n) {
  rand <- rnorm(n)
  no   <- seq_len(n)
  df   <- data.frame(no=no, rand=rand)
  if (n > 10) {
    png("plot.png")
    p <- ggplot(df)
    p + geom_point(aes(x=no, y=rand))
    dev.off()
  }
}

f(11)

I get a blank png file at the end of this. What is going on here?

lmo
  • 37,904
  • 9
  • 56
  • 69
imanuelcostigan
  • 3,459
  • 3
  • 17
  • 19
  • 8
    It's a [FAQ](http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-do-lattice_002ftrellis-graphics-not-work_003f) and you should be using `ggsave` anyway. – joran Feb 09 '12 at 06:07
  • 2
    possible duplicate of [ggplot's qplot does not execute on sourcing](http://stackoverflow.com/questions/6675066/ggplots-qplot-does-not-execute-on-sourcing) – joran Feb 09 '12 at 06:49
  • 2
    possible duplicate of [Save ggplot within a function](http://stackoverflow.com/questions/7034647/save-ggplot-within-a-function) – Tyler Rinker Feb 09 '12 at 06:58
  • 3
    we need an `faq` package, with a function that crawls the Web and ranks entries according to their citations. Default R startup message would display a random faq, where some of us may use `fortune()`. – baptiste Feb 09 '12 at 08:19
  • @baptise did you write the script to do that? I actually think that would be an awesome idea :) +1 – Tyler Rinker Feb 09 '12 at 14:55
  • @TylerRinker no, sadly I've never found the time to write this [`fraq` package.](http://tolstoy.newcastle.edu.au/R/e11/help/10/08/4268.html) – baptiste Feb 09 '12 at 21:17

2 Answers2

36

From responses, here are two solutions:

library(ggplot2)
f <- function(n) {
  rand <- rnorm(n)
  no   <- seq_len(n)
  df   <- data.frame(no=no, rand=rand)
  if (n > 10) {
    png("plot.png")
    print({
      p <- ggplot(df)
      p + geom_point(aes(x=no, y=rand))
    })
    dev.off()    
  }
}

f(11)

Note: I was aware that I needed to use print(), but the way I tried this didn't work because it wasn't placed in the right place.

Also, I had tried the ggsave option previously, but that didn't work either. Of course, it now works as well. It also seems to have a better resolution than using png():

library(ggplot2)
f <- function(n) {
  rand <- rnorm(n)
  no   <- seq_len(n)
  df   <- data.frame(no=no, rand=rand)
  if (n > 10) {
    p <- ggplot(df)
    p + geom_point(aes(x=no, y=rand))
    ggsave(file="plot.png")
  }
}

f(11)

Thanks all.

imanuelcostigan
  • 3,459
  • 3
  • 17
  • 19
  • You can accepted your own answer. Shows everyone your question has been solved. – Paul Hiemstra Nov 04 '12 at 23:09
  • FYI, you can set desired resolution using png(). For example if you want an image at 300 dpi and 6 inches square, you can call png('plot.png', height = 6, width = 6, res = 300, units = 'in') – qdread Nov 28 '17 at 16:13
15

I just learned from other website (link provided below). In a loop you have to explicitly use print function in order to make jpeg(), png() function to work. In the original post, you can just add a line of print(p).

  if (n > 10) {
        png("plot.png")
        p <- ggplot(df)
        p + geom_point(aes(x=no, y=rand))
        print(p)
        dev.off()
    }

In the link below, it provides a good explanation for this https://stat545-ubc.github.io/block017_write-figure-to-file.html#despair-over-non-existent-or-empty-figures

maRtin
  • 6,336
  • 11
  • 43
  • 66
Zhengyu Pang
  • 159
  • 1
  • 4