Search code examples
rplot

How to combine two base plots in R?


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

Solution

  • 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