6

Since it is possible to export R plots to PDF or PNG or SVG etc., is it also possible to export an R plot to multiple formats at once? E.g., export a plot to PDF and PNG and SVG without recalculating the plot?

Wouter Beek
  • 3,307
  • 16
  • 29
  • Not with base graphics, with package `ggplot2` yes. – Rui Barradas Jan 06 '18 at 21:58
  • 3
    I'd say not even with ggplot2. The ggplot2 and other grid solutions create a plotting program that is then passed to a print engine before being sent to a device. They will need to be "recalculated" every time they are `print`-ed. – IRTFM Jan 06 '18 at 22:15
  • Excuse me, do you find anyone's answer useful? – ytu Jan 23 '18 at 15:24
  • @ytu IINM the current answers seem to recalculate the plot for each output device? If that is the case then user 42 gave the correct answer, but in a comment. – Wouter Beek Jan 27 '18 at 12:29
  • I'd say not really. If you're using `dev.copy`, according to its document, it "*copies the graphics contents of the current device to the device specified*", i.e. the plot is not recalculated, but copied. On the other hand, `sapply` is a function doing iteration at C level (you can find related discussions [here](https://stackoverflow.com/questions/28983292/is-the-apply-family-really-not-vectorized)). You may call it "recalculating", but it is typically much faster than a `for` loop for the same job. – ytu Jan 27 '18 at 13:48

2 Answers2

6

Without using ggplot2 and other packages, here are two alternative solutions.

  1. Create a function generating a plot with specified device and sapply it

    # Create pseudo-data
    x <- 1:10
    y <- x + rnorm(10)
    
    # Create the function plotting with specified device
    plot_in_dev <- function(device) {
      do.call(
        device,
        args = list(paste("plot", device, sep = "."))  # You may change your filename
      )
      plot(x, y)  # Your plotting code here
      dev.off()
    }
    
    wanted_devices <- c("png", "pdf", "svg")
    sapply(wanted_devices, plot_in_dev)
    
  2. Use the built-in function dev.copy

    # With the same pseudo-data
    # Plot on the screen first
    plot(x, y)
    
    # Loop over all devices and copy the plot there
    for (device in wanted_devices) {
      dev.copy(
        eval(parse(text = device)),
        paste("plot", device, sep = ".")  # You may change your filename
      )
      dev.off()
    }
    

The second method may be a little tricky because it requires non-standard evaluation. Yet it works as well. Both methods work on other plotting systems including ggplot2 simply by substituting the plot-generating codes for the plot(x, y) above - you probably need to print the ggplot object explicitly though.

ytu
  • 1,822
  • 3
  • 19
  • 42
0

Yes, absolutely! Here is the code:

library(ggplot2)
library(purrr)
data("cars")
p <- ggplot(cars, aes(speed, dist)) + geom_point()

prefix <- file.path(getwd(),'test.')

devices <- c('eps', 'ps', 'pdf', 'jpeg', 'tiff', 'png', 'bmp', 'svg', 'wmf')

walk(devices,
     ~ ggsave(filename = file.path(paste(prefix, .x)), device = .x))
AlphaDrivers
  • 136
  • 4