5

In a number of scripts I first develop a graph on screen, and then need to save it as several file formats with particular height/width/resolution. Using png(), pdf(), svg(), ... to open a device, and then dev.off() to close it, I'm forced to put all the device open calls into my script and comment them out & re-run the code one device at a time.

I do know that for ggplot graphics, ggsave() makes this easier. Is there any thing I can do to simplify this for base-R and lattice graphics?

One example:

png(filename="myplot.png", width=6, height=5, res=300, units="in")
# svg(filename="myplot.svg", width=6, height=5)
# pdf(filename="myplot.pdf", width=6, height=5)

op <- par()  # set graphics parameters
plot()       # do the plot
par(op)
dev.off() 
user101089
  • 3,756
  • 1
  • 26
  • 53

2 Answers2

2

The graphics devices are part of the grDevices package. The documentation on working with multiple open devices might be worth reading through. From what I understand, a circular array of open devices is stored, but only the current device is active. For that reason, opening all the desired devices and then looping over them with dev.list() is likely your best bet.

# data for sample plot
x <- 1:5
y <- 5:1

# open devices
svg(filename="myplot.svg", width=6, height=5)
png(filename="myplot.png", width=6, height=5, res=300, units="in")
pdf()

# devices assigned an index that can be used to call them
dev.list()
svg png pdf 
  2   3   4 

# loop through devices, not sure how to do this without calling plot() each time
# only dev.cur turned off and dev.next becomes dev.cur
for(d in dev.list()){plot(x,y); dev.off()} 

# check that graphics device has returned to default null device
dev.cur()
null device 
      1 
dev.list()
NULL

file.exists("myplot.svg")
[1] TRUE
file.exists("myplot.png")
[1] TRUE
file.exists("Rplots.pdf") # default name since none specified in creating pdf device
[1] TRUE

There's quite a bit more in the documentation that you can work with.

Conner M.
  • 1,954
  • 3
  • 19
  • 29
1

You could use the cowplot package to convert your base or lattice graphics into ggplot2 objects that you can then save via ggsave(). This is not entirely foolproof but will work for most plots. You'll also need to install the gridGraphics package for this to work. See more here.

library(ggplot2)
library(cowplot)
#> 
#> ********************************************************
#> Note: As of version 1.0.0, cowplot does not change the
#>   default ggplot2 theme anymore. To recover the previous
#>   behavior, execute:
#>   theme_set(theme_cowplot())
#> ********************************************************

# define a function that emits the desired plot
p1 <- function() {
  par(
    mar = c(3, 3, 1, 1),
    mgp = c(2, 1, 0)
  )
  boxplot(mpg ~ cyl, xlab = "cyl", ylab = "mpg", data = mtcars)
}

# the plot using base graphics
p1()


# the plot converted into a ggplot2 object
p2 <- ggdraw(p1)
p2


# save in different formats
ggsave("plot.pdf", p2)
#> Saving 7 x 5 in image
ggsave("plot.png", p2)
#> Saving 7 x 5 in image
ggsave("plot.svg", p2)
#> Saving 7 x 5 in image

Created on 2020-01-05 by the reprex package (v0.3.0)

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104