How to combine two base plots in R?

65 Views Asked by At
my.date <- seq(as.POSIXct("2014-10-14 00:00:00", format="%F %T"), 
               by="hour", 
               length.out=6*128*24)  

library('WaveletComp')
x <- periodic.series(start.period=1*24, length=6*128*24)
my.data <- data.frame(date=my.date, x=x)

my.wt <- analyze.wavelet(my.data, "x",                   
                         loess.span=0, 
                         dt=1/24, dj=1/20, 
                         lowerPeriod=1/4, 
                         make.pval=TRUE, n.sim=10)


layaout2 <- layout(matrix(c(1, 2, 3), nrow=3))
wt.image(my.wt, main="wavelet power spectrum",
         legend.params=list(lab="wavelet power levels (quantiles)", 
                              lab.line=3.5, 
                              label.digits=2),
         periodlab="period (days)")
p1 <- recordPlot() 
wt.image(my.wt, main="wavelet power spectrum",
         legend.params=list(lab="wavelet power levels (quantiles)", 
                              lab.line=3.5, 
                              label.digits=2),
         periodlab="period (days)")
p2 <- recordPlot()
plot_grid(p1, p2,
          labels='AUTO',
          hjust=0, vjust=1)

I got error

Error in if (labels) { : missing value where TRUE / FALSE is required
2

There are 2 best solutions below

9
jay.sf On BEST ANSWER

Apparently you can't place "recordedplot" objects on a layout.

Not sure why you want use grDevices::recordPlot at all, maybe you want to mimick some sort of ggplot behavior. However, base plot, or WaveletComp::wt.image which uses it, will always complete plotting, so you would always see your plots twice.

So you may stick with layout or use par(mfrow=) as in @robert-hacken's answer, and set graphics.reset=FALSE according to his advice.

I recommend using the png device rather than RStudio preview window; it's much faster and produces hard-coded image size. Plot is stored in working directory (or use png('/<path>/foo.R')). If you don't want use it, just comment out png and dev.off line:

png('foo.png', 800, 600)  ## open png device

layout(matrix(c(1, 2), nrow=2))
par(mar=c(3, 3, 3, 3) + .6)  ## slightly reduce margins
wt.image(my.wt, main="wavelet power spectrum",
         legend.params=list(lab="wavelet power levels (quantiles)", 
                            lab.line=3.5, 
                            label.digits=2),
         periodlab="period (days)",
         graphics.reset=FALSE)
wt.image(my.wt, main="wavelet power spectrum",
         legend.params=list(lab="wavelet power levels (quantiles)", 
                            lab.line=3.5, 
                            label.digits=2),
         periodlab="period (days)",
         graphics.reset=FALSE)

dev.off()  ## close png device

enter image description here

Note: Don't use layout together w/ par(mfrow=, mfcol=) options, as they are not compatible.

Update

To combine multiple analyses in a plot, store first analyses in a list, then loop over the list to plot. Example:

my.data3 <- my.data2 <- my.data1 <- my.data

my.wt_lst <- Map(
  analyze.wavelet,
  my.data=list(my.data1, my.data2, my.data3),
  my.serie='x',
  loess.span=c(0, .25, .5),
  dt=1/24,
  dj=1/20,
  lowerPeriod=1/4,
  make.pval=TRUE,
  n.sim=10
)

Map loops over elements synchronously, i.e. if there's just one as in dt=1/24 it will always use 1/24, if there's multiple as in my.data=list(my.data1, my.data2, my.data3), or loess.span=c(0, .25, .5), it will use the elements one by one. Note, that a list or data.frame itself is a list w/ multiple elements, and you'd need to list it again, e.g. my.data=list(my.data1) instead of just my.data=my.data1.

png('foo.png', 1200, 600)
layout(matrix(seq_along(my.wt_lst), nrow=length(my.wt_lst)))
par(mar=c(3, 3, 3, 3) + .6)  ## slightly reduce margins
for (i in seq_along(my.wt_lst)) {
  wt.image(my.wt_lst[[i]], main="wavelet power spectrum",
           legend.params=list(lab="wavelet power levels (quantiles)", 
                              lab.line=3.5, 
                              label.digits=2),
           periodlab="period (days)",
           graphics.reset=FALSE)
}
dev.off()

enter image description here

1
Robert Hacken On

You can use standard base R methods, e.g. par(mfrow=c(2, 1)). Just make sure to set graphics.reset=F for wt.image() as otherwise it will reset the original graphical parameters when finishing, which notably reapplies the mfrow setting and the next plot will be put on a new page.

par(mfrow=c(2, 1))
wt.image(my.wt, main = "wavelet power spectrum",
         legend.params = list(lab = "wavelet power levels (quantiles)", 
                              lab.line = 3.5, 
                              label.digits = 2),
         periodlab = "period (days)",
         graphics.reset=F)
wt.image(my.wt, main = "wavelet power spectrum",
         legend.params = list(lab = "wavelet power levels (quantiles)", 
                              lab.line = 3.5, 
                              label.digits = 2),
         periodlab = "period (days)",
         graphics.reset=F)

two plots