Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving plots in R within a loop

Tags:

r

ggplot2

Yesterday I upgraded R to version 3.0.0 and ggplot2 to version 0.9.3.1 (and made a few minor changes to my script). Now I am getting errors when attempting to save plots - unfortunately the error is not reproduced with a smaller dataframe, so I have included code to generate one of the same size.

library("ggplot2")

# Create data frame
# Time interval ID (x)
bin.ts.avg <- as.data.frame(rep(1:18, 31))
names(bin.ts.avg) <- "x"
# Time (sequence of 10 minuter intervals between 7am and 10am)
tt.month.bins <- seq(from=as.POSIXct("2012-01-01 GMT"), to=as.POSIXct("2012-01-01 GMT") + 60*60*24*31, by="10 mins")
tt.month.bins <- tt.month.bins[-length(tt.month.bins)]
temp <- as.numeric(format(tt.month.bins, "%H"))
ind <- which(temp >=7 & temp <= 9)  
tt.month.bins <- tt.month.bins[ind]
bin.ts.avg$dep <- tt.month.bins
# Value (with some NA)
bin.ts.avg$tt <- runif(558, min=2.5, max=5)
bin.ts.avg$tt[trunc(runif(200, min=1, max=558))] <- NA
# Day
bin.ts.avg$depday <- rep(1:31, each=18)

for (i in 1:2){
  if (1){
    hist(rnorm(100))
    dev.print(file="MyHist.png",device=png, bg="white",  width=640, height=352) 

    p <- ggplot(bin.ts.avg, aes(x, tt)) + geom_point() +geom_line() + facet_grid(.~depday)
    p <- p + ggtitle("10 minute averages")+ xlab("Hour") + ylab("Values")    
    p <- p + scale_x_continuous(breaks=c(min(bin.ts.avg$x), max(bin.ts.avg$x)), labels=c("7", "10"))
    print(p)  
    dev.print(file="MyGGPlot.png",device=png, bg="white",  width=640, height=352) 
  }
}

On running this script, I receive the following error message:

Error in UseMethod("depth") : no applicable method for 'depth' applied to an object of class "NULL"

However, if I run the script line by line everything runs okay (picture below). How the ggplot should look Now if I change the for loop and use dev.copy and ggsave instead of dev.print as below

for (i in 1:2){
  if (1){
    hist(rnorm(100))
    dev.copy(file="MyHist.png",device=png, bg="white",  width=640, height=352) 
    dev.off()

    p <- ggplot(bin.ts.avg, aes(x, tt)) + geom_point() +geom_line() + facet_grid(.~depday)
    p <- p + ggtitle("10 minute averages")+ xlab("Hour") + ylab("Values")    
    p <- p + scale_x_continuous(breaks=c(min(bin.ts.avg$x), max(bin.ts.avg$x)), labels=c("7", "10"))
    print(p)  
    ggsave(filename="MyGGPlot.png")
  }
}

On attempting to open "MyGGPlot.png" using Paint, I receive an error message stating

A sharing violation occurred while accessing <filename>

I run the script using RStudio version 0.97.449. Any ideas on what I need to change in order to save current plots?

like image 723
user1420372 Avatar asked Apr 23 '13 05:04

user1420372


People also ask

How do I save multiple plots in R?

To save multiple plots to the same page in the PDF file, we use the par() function to create a grid and then add plots to the grid. In this way, all the plots are saved on the same page of the pdf file. We use the mfrow argument to the par() function to create the desired grid.

How do you save a plot in R?

Plots panel –> Export –> Save as Image or Save as PDF It's also possible to save the graph using R codes as follow: Specify files to save your image using a function such as jpeg(), png(), svg() or pdf(). Additional argument indicating the width and the height of the image can be also used.

Does Ggplot work in for loop?

r - ggplot does not work if it is inside a for loop although it works outside of it - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.

How do I save multiple Ggplots in R?

To save multiple ggplots using for loop, you need to call the function print() explicitly to plot a ggplot to a device such as PDF, PNG, JPG file. Enjoyed this article?


1 Answers

A couple of points

Use graphics.off() after dev.copy. This will close all graphics devices. You could also call dev.off() twice (but graphics.off() is a wrapper that will basically call dev.off() sufficient times to close all graphics devices

ggsave doesn't require a printed object (this is not a case where FAQ 7.22 is relevant).

The default is the value of last_plot which is the last ggplot object created, modified or printed. So creating p is sufficient for ggsave('filname.png') to save that object.

for (i in 1:2){
  if (1){
    hist(rnorm(100))
    dev.copy(file="MyHist.png",device=png, bg="white",  width=640, height=352) 
    graphics.off()

    p <- ggplot(bin.ts.avg, aes(x, tt)) + geom_point() +geom_line() + facet_grid(.~depday)
    p <- p + ggtitle("10 minute averages")+ xlab("Hour") + ylab("Values")    
    p <- p + scale_x_continuous(breaks=c(min(bin.ts.avg$x), max(bin.ts.avg$x)), labels=c("7", "10"))
   # no need to print p
   ggsave(filename="MyGGPlot.png")
   # note specifying p is redundant but explicit.
   # ggsave(filename = 'MyGGplot.png', plot = p)
  }
}
like image 94
mnel Avatar answered Sep 20 '22 18:09

mnel