R script that should plot xts class data to a png file doesn't produce a png file - r

I had a working script that used a loop to produce many png file plots of xts class data. Now the script throws an error and if I comment out the line throwing the error (a call to abline() ) then the script executes but without producing a png file. The issue seems to involve plotting xts class data and/or a loop or script.
Searching on stackoverflow didn't provide a solution or reference to this issue. I've reproduced the issue in the following example. In practice, the script would use different filenames within the loop and non-trivial data.
# put following code in 'myscript.R' and execute using source('myscript.R',print.eval=TRUE) or source('myscript.R')
# xts class data
data <- xts(seq(1:10),order.by=as.Date(seq(1:10)))
# a non xts version of same data
#data <- seq(1:10)
for(i in 1:1) {
filename <- 'myfile.png'
png(filename)
plot(data)
lines( (data-1),col='red')
abline(h=1)
dev.off()
}
# The call to abline in above script with xts class data gives error 'plot.new has not been called yet'
# If comment out the call to abline it completes but doesn't produce a png file
# script works fine with abline for non xts data

Using xts >= 0.10.1, this saves to file what you want
for(i in 1:1) {
filename <- 'myfile.png'
png(filename)
plot(data)
print(lines( (data-1),col='red', on = 1))
print(lines(xts(x = rep(1, NROW(data)), order.by = index(data)),col='green', on= 1) )
dev.off()
}
Use the print calls for the extra lines. I'd also use lines for the horizonal line, instead of abline, as this is more consistent with plotting with xts.
Also your error can be avoided if you do print(abline(h=1))

Related

How to save several plots from an own function into a list in R?

I have created one function that contains two types of plots and it will give you one image. However, the title of this image will change depending on one list, so, you will have several plots but different title.
(The original function will change the numbers that the plot uses but, in essence, is what I need).
This is the example that I have created.
list_genes <- c("GEN1", "GEN2", "GEN3")
myfunction <- function(x,y){
for(gene in list_genes){
# This to draw both plots
par(mfrow=c(2,1))
plot(x,y, main=paste0("Plot of ", gene))
hist(x, main=paste0("Plot of ", gene))
}
}
myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
Since the list has 3 elements, we get 3 plots.
However, as I need to create a presentation with all the plots that I generate, I found this post with a solution to create slides for several plots inside a for loop. It is what I want, but for that, I need to save my plots into a list/variable.
object <- myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
> object
NULL
I found this post (which gives you an interesting solution) but, the plots still cannot be saved into an object.
calling_myfunc <- function(){
myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
}
calling_myfunc()
object <- calling_myfunc()
> object
NULL
My final objective is to create a presentation (automatically) with all of the plots that I generate from my function. As I saw in this post. But I need to save the plots into a variable.
Could anyone help me with this?
Thanks very much in advance
Although I couldn't find the way to save the plots into an object, I found a way to create a presentation with those images thanks to this post and the export package.
library(export)
list_genes <- c("GEN1", "GEN2", "GEN3")
myfunction <- function(x,y){
for(gene in list_genes){
# This to draw both plots
par(mfrow=c(2,1))
plot(x,y, main=paste0("Plot of ", gene))
hist(x, main=paste0("Plot of ", gene))
graph2ppt(file="plots.pptx", width=6, height=5,append=TRUE) } }
myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
Of course, the width and height of the plots can be changed or put them as a parameter in the function.
Since the package is not available in CRAN for my current R version (4.1.2), I downloaded it from GitHub:
devtools::install_github("tomwenseleers/export")
In addition, I have found another package that I can use for the same purpose (although it adds one extra slide at the beginning, I don't know why)
library(eoffice)
list_genes <- c("GEN1", "GEN2", "GEN3")
myfunction <- function(x,y){
for(gene in list_genes){
# This to draw both plots
par(mfrow=c(2,1))
plot(x,y, main=paste0("Plot of ", gene))
hist(x, main=paste0("Plot of ", gene))
topptx(file="plots.pptx", width=6, height=5,append=TRUE)
}
}
myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
PS: I found the solution to create a presentation --> How to create a presentation in R with several plots obtained by a function?

R autoplot works when running line-by-line but not when source-ing R script

I'm observing a very strange behaviour with R.
The following code works when I type it in line-by-line into an instance of R run from my terminal. (OS is Debian Linux.)
However it does not work when I try and run source("script.R").
It also does not work from within R Studio.
Specifically, it fails to produce graphical output with autoplot. Writing to pdf file does not work, and if I remove the pdf() and dev.off() lines, no window containing the figure is opened.
Here's a copy of my script...
library(lubridate)
library(ggplot2)
library(matrixStats)
library(forecast)
df_input <- read.csv("postprocessed.csv")
x <- df_input$time
y <- df_input$value
df <- data.frame(x, y)
x <- df$x
y <- df$y
holtmodel <- holt(y)
pdf("autoplot.pdf")
autoplot(holtmodel)
dev.off()
And for convenience, here's a datafile.
"","time","value"
"1",1,2.61066016308988
"2",2,3.41246054742996
"3",3,3.8608767964033
"4",4,4.28686048552237
"5",5,4.4923132964825
"6",6,4.50557049744317
"7",7,4.50944447661246
"8",8,4.51097373134893
"9",9,4.48788748823809
"10",10,4.34603985656981
"11",11,4.28677073671406
"12",12,4.20065901625172
"13",13,4.02514194962519
"14",14,3.91360194972916
"15",15,3.85865748409081
"16",16,3.81318053258601
"17",17,3.70380706527433
"18",18,3.61552922363713
"19",19,3.61405310598722
"20",20,3.64591327503384
"21",21,3.70234435835577
"22",22,3.73503970503372
"23",23,3.81003078640584
"24",24,3.88201196162666
"25",25,3.89872518158949
"26",26,3.97432743542362
"27",27,4.2523675144599
"28",28,4.34654855854847
"29",29,4.49276038902684
"30",30,4.67830892029687
"31",31,4.91896819673664
"32",32,5.04350767355202
"33",33,5.09073406942046
"34",34,5.18510849382162
"35",35,5.18353176529036
"36",36,5.2210776270173
"37",37,5.22643491929207
"38",38,5.11137006553725
"39",39,5.01052467981257
"40",40,5.0361056705898
"41",41,5.18149486951409
"42",42,5.36334869132276
"43",43,5.43053620818444
"44",44,5.60001072279525
Pretty confused because it seems like a trivial script!
change it to:
print(autoplot(holtmodel))
When you step through code, you get an implicit print(...) statement on each code line. When you source() you don't. ggplot (and others!) use print() to trigger their ploting (so that you can conveniently build up a plot step by step without having to wait for flickering figures)

R: How to save plot of "find_droughts" function from "lfstat" package as an image using code?

When I try to save this particular plot as an image, I only get an empty white image file. With this same code I managed to save multiple other "normal" plots, but it just won't work for find_droughts function (maybe also for some others).
I can save the plot manually by clicking "Export" in the Viewer, but I have a lot of plots to save and I would really like to do it using code.
This code generates the plot I have in mind:
library(lfstat)
# random data
date<-seq(from=as.Date("2018-01-01"), to=as.Date("2018-12-31"), by="days")
flow<-c(runif(150, min=50, max=180),runif(95, min=25, max=50),runif(120, min=50, max=400))
# dataframe
flow.df<-data.frame(day(date),month(date),year(date),flow)
names(flow.df)<-c("day", "month", "year", "flow")
#dataframe to lfobj
lfobj <- createlfobj(flow.df,hyearstart = 1, baseflow = FALSE)
# lfobj to xts
flowunit(lfobj)<-"m^3/s"
xts<-as.xts(lfobj)
# find droughts
droughts<-find_droughts(xts, threshold=47, drop_minor = 0)
# Save plot as .png
savehere<-"C:/.../"
filename<-"myplot.png"
mypath <- file.path(paste(savehere,filename, sep = ""))
png(file=mypath)
plot(droughts)
dev.off()
I need help with the last step - "# Save plot as .png".
And if anybody knows a way to change title of this plot, names of axis labels and so on, this would also help.
I think the reason is that the default plot from the 'find_droughts' function is an interactive plot based on dygraph package.
I can think of two ways to overcome your issue.
If you want to plot static png, you can define on the plot function the type of the plot, so it's not the default (interactive) anymore. Based on your code, it will be:
# Save plot as .png
savehere <- "C:/.../"
filename <- "myplot.png"
mypath <- file.path(paste(savehere,filename, sep = ""))
png(file=mypath)
plot(droughts, type='l') # by defining type 'l', it will provide a plot of xts object, which is static
dev.off()
If you want to plot an interactive plot, you can do something as below:
# Save plot as .html
library(htmlwidgets) # for saving html files
savehere <- "C:/.../"
filename <- "myplot.html"
mypath <- file.path(paste(savehere,filename, sep = ""))
InteractivePlot <- plot(droughts)
saveWidget(InteractivePlot , file=mypath)
# the above function will generate the interactive plot as an html file, but also a folder, which you might want to delete, since it's not required for viewing the plot. For deleting this folder you can do the following
foldername <- "myplot_files"
mypath <- file.path(paste(savehere,foldername , sep = ""))
unlink(mypath, recursive = T)
Hope this helps.

R plot loop problems with last image

I've created a script for calculating several model for regression. I made a triple loop to save the results of the model in a list and then I can call whatever I need for plotting etc. I've then created other three loop for plotting my data. Everything seems to work but the last loop of the cycle create a pdf file for the plots it gets hang and corrupted. I can, of course, add dummy data in order to have the correct plot that I need but I cannot understand what it is.
I've tried all the options for graphics.off() and dev.off() but it seems I get something wrong. my R 3.3.2 version Any help appreciated
Plot DSC thermograms of isothermal crysallization
for (intK in 1:nrow(sample_levels)) #the levels of my sample
{ for (intJ in 1:nrow(conc_levels)) #concentration levels of my samples
{
plot(0,0,type='n', xlim=c(0,lim_Max_Time) ,ylim=c(0,lim_Max_exo_up),xlab=expression(paste("Time(s)")),ylab=expression(paste("Heat flow (J/g) -exo up")) ) #create null plot
for (intL in 1:nrow(Temperatures_levels))
{
if (!is.null(matrix_Avrami[[intK,intJ,intL]] ))
{
data_plot <-matrix_Avrami[[intK,intJ,intL]] #recall my data from previous part in the script
Time_p=data_plot[5] #choose the x I need
Time_p<-as.matrix(Time_p) #to avoid Error in xy.coords(x, y) : 'x' and 'y' lengths differ
Heat_flow_exo_up<-data_plot[4] #my y
Heat_flow_exo_up<-as.matrix(Heat_flow_exo_up) #same as before for avoiding erro
points(Time_p,Heat_flow_exo_up,pch=intL) #create correctly the plot I need
}
}
title(main=paste("Conc",as.character(conc_levels[intJ,]),"% GO",as.character(sample_levels[intK,]), sep = " " ) )
legend ("topright", paste(as.character(Temperatures_levels[,]),"°C",sep = ""),pch=1:nrow(Temperatures_levels))
mypath <- file.path("C:","R","SAVEHERE",paste("Heat_flow_vs_Time", as.character(intK),as.character(intJ),".pdf", sep = ""))
pdf(file=mypath)
}
dev.off()
} #the last plot of the loop correctly visualized in my console

Use of recordPlot() and replayPlot() in Parallel in R to save plot in the same PDF

I would like to plot data in parallel using foreach in R but I didn't find any way to get all my plots in the same pdf file. I thought of using recordPlot to save my plots in a list and then print them in a pdf device but it doesn't work.
I have the following error :
Error in replayPlot(x) : loading snapshot from a different session
I tried as well with ggplot but this is to slow with my large dataset.
Here is a piece of code showing my problem :
# Creating a dataframe : df
df=as.data.frame(matrix(nrow=1, ncol=10))
df=apply(df, 2, function(x) runif(100))
# Plotting function
par.plot=function(dat){
plot(dat)
p=recordPlot()
return(p)}
#Applying the function in parallel
library("parallel")
library("foreach")
library("doParallel")
cl <- makeCluster(detectCores())
registerDoParallel(cl, cores = detectCores())
plot.lst = foreach(i = 1:nrow(df)) %dopar% {
par.plot(df[i,])
}
# Trying to get 1st plot
plot.lst[[1]]
Error in replayPlot(x) : loading snapshot from a different session
Replacing %dopar% by %do% is working when I try to get my plots, because they seems to have been generated in the same environment.
I know I can call a pdf device inside the loop to generate a file for each iteration, but I would like to know if there is a way to get one file for all my plots at the output of my function.
Or do you know an easy way to merge my pdf files afterwards ?
Thanks for your help.
Charles
In my opinion your question can be devided into two distinctive parts:
1. Using the replayPlot function in th%dopar% without getting the weird error
2. Somehow getting 1 file at the end
The first question is easy to answer. The reason you get this error is that the R somehow remembers where (in OS level) the plots has been generated. You can get the same effect by using Rstudio server and trying to replay some of the recorded plots after couple of hours of closing the browser tab. In brief, the issue is that R remembers the PID of the process that generated the plot (Don't know why though!):
# generate a plot
plot(iris[, 1:2]
# record the plot
myplot <- recordPlot()
# check the PID
attr(x = myplot, which = "pid")
the good thing is you can overwrite this by assigning your current PID:
attr(x = myplot, which = "pid") <- Sys.getpid()
so you should only change the last line of your code to the following:
pdf(file = "plot.lst.pdf"))
graphics.off()
lapply(plot.lst, function(x){
attr(x = x, which = "pid") <- Sys.getpid()
replayPlot(x)})
graphics.off()
The part above entirely solves your problem, but in case you are interested in merging PDF files, follow this discussion:
Merging existing PDF files using R

Resources