Search code examples
rgraphicstime-seriestimeserieschart

How to plot a two-columned grid of time series with custom titles using R?


I have the following code (although without data, sadly):

detrend_plot <- cbind(l_p_lng,l_vol_lng,l_p_oil,l_rgdpe, ldiff_p_lng,ldiff_vol_lng,ldiff_p_oil,ldiff_rgdpe)

plot.ts(detrend_plot, main="",)

which gives the following plot:

enter image description here

What I want to do is to add custom titles, individual y-axis labels, and x-axis labels. I know that this is possible using GGPLOT, although my knowledge of it is sparse. Has anyone encountered a similar problem? I don't think this is possible using the regular plot.ts( ) function.


Solution

  • I don't think you can pass multiple titles and labels to plot.ts directly, but you can just loop over your columns with vectors of labels for each:

    set.seed(1)
    z <- ts(matrix(rt(200 * 8, df = 3), 200, 8), start = c(1961, 1), frequency = 12)
    
    ## vectors of x, y, and main labels
    xl <- sprintf('x label %s', 1:8)
    yl <- sprintf('y label %s', 1:8)
    ml <- sprintf('main label %s', 1:8)
    
    par(mfrow = c(4, 2), mar = c(5, 5, 1, 1), oma = c(0, 0, 1, 2))
    lapply(1:8, function(ii) {
      x <- z[, ii, drop = FALSE]
      plot(x, xlab = xl[ii], ylab = yl[ii], main = ml[ii])
    })
    

    enter image description here

    You can also pass vectors of arguments (eg, for x- or y-axis limits) using lists:

    ylim <- list(c(-10, 10))
    ylim <- rep(ylim, 8)
    
    par(mfrow = c(4, 2), mar = c(5, 5, 1, 1), oma = c(0, 0, 1, 2))
    lapply(1:8, function(ii) {
      x <- z[, ii, drop = FALSE]
      plot(x, xlab = xl[ii], ylab = yl[ii], main = ml[ii], col = ii, ylim = ylim[[ii]])
    })
    

    enter image description here

    To get a figure closer to the default plot.ts look, you can just set top and bottom margins to 0 and adjust the axes (which is what plot.ts is doing under the hood). This method is a bit more verbose than plot.ts but will allow for more customization:

    par(mfrow = c(4, 2), mar = c(0, 5, 0, 1), oma = c(5, 0, 3, 2))
    lapply(1:8, function(ii) {
      x <- z[, ii, drop = FALSE]
      plot(x, xlab = xl[ii], ylab = yl[ii], col = ii, axes = FALSE)
      axis(2, las = 1)
      box()
      if (ii %in% 7:8) {
        axis(1)
        title(xlab = 'Year', xpd = NA)
      }
      if (ii %in% 1:2)
        title(main = c('Group 1', 'Group 2')[ii], xpd = NA, line = 1)
    })
    

    enter image description here