danpo
danpo

Reputation: 35

Using ggplot with figure functions

I'm trying to get the idea of figure functions I got from the Nice R Code blog to run with my ggplot-based plots.

Let me quickly review their idea: Basically it's just a way to increase readability and structure when plotting to a file. Instead of having to open a plotting device, generate the plot and then close the device with dev.off(), the suggested way is to separate the two tasks by defining one function that generates the figure and another function to write it to a file.

to.dev <- function(expr, dev, filename, ..., verbose=TRUE) { 
  if (verbose) {
    cat(sprintf("Creating %s\n", filename))
  }

  dev(filename, ...)
  on.exit(dev.off())
  eval.parent(substitute(expr))
} 

to.png <- function(expr, filename, ..., verbose=TRUE) {
  to.dev(expr, png, filename)
}

fig.progressive <- function(with.trend=FALSE) {
  set.seed(10)
  x <- runif(100)
  y <- rnorm(100, x)
  par(mar=c(4.1, 4.1, .5, .5))
  plot(y ~ x, las=1)
  if ( with.trend ) {
    fit <- lm(y ~ x)
    abline(fit, col="red")
    legend("topleft", c("Data", "Trend"),
           pch=c(1, NA), lty=c(NA, 1), col=c("black", "red"), bty="n")
  }
}

Eventually I just have to write one line to output the figure:

to.png(fig.progressive(TRUE), "figs/base.png", width = 6, height = 4)

This works like a charm and is awesome if you have to do these sorts of things for a lot of figures. However, it doesn't work with ggplot. When trying something like this:

fig.progressive.ggplot <- function(with.trend=FALSE) {
  set.seed(10)
  df.x <- runif(100)
  df.y <- rnorm(100, df.x)
  df <- data.frame(df.x, df.y)
  plot <- ggplot(data = df, aes(x = df.x, y = df.y)) + geom_point()
  if ( with.trend ) {
    plot <- plot + geom_smooth()
  }
  plot
}

and then writing it to a device using

to.png(fig.progressive(TRUE), "figs/ggplot.png", width = 6, height = 4)

nothing happens. The code is run, but there's no figs/ggplot.png file.

I have read about other users having issues with ggplot in environments other than the global environment and thought this might relate to my problem here. But I couldn't figure out, what the problem really is.

I'd be grateful for a solution to this problem and/or other suggestions about how to write clean, readable code when outputting several figures.

Upvotes: 1

Views: 173

Answers (1)

Josh W.
Josh W.

Reputation: 1143

The proper way to save ggplot figures is with ggsave . See http://docs.ggplot2.org/current/ggsave.html .

If you do not want to use ggsave, just change plot to print(plot) . See http://www.cookbook-r.com/Graphs/Output_to_a_file/

i.e. :

fig.progressive.ggplot <- function(with.trend=FALSE) {
  set.seed(10)
  df.x <- runif(100)
  df.y <- rnorm(100, df.x)
  df <- data.frame(df.x, df.y)
  plot <- ggplot(data = df, aes(x = df.x, y = df.y)) + geom_point()
  if ( with.trend ) {
    plot <- plot + geom_smooth()
  }
  print(plot)
}

Upvotes: 1

Related Questions