R/plot.str.R

Defines functions plot.STR getDataToPlot createLayoutMatrix getLegend getYlab getLimits

Documented in plot.STR

#' @importFrom graphics Axis
#' @importFrom graphics abline
#' @importFrom graphics layout
#' @importFrom graphics legend
#' @importFrom graphics lines
#' @importFrom graphics mtext
#' @importFrom graphics par
#' @importFrom graphics plot
#' @importFrom graphics plot.new
#' @importFrom graphics polygon

getLimits <- function(l) {
  d <- lapply(l, FUN = function(x) c(x$data, x$upper, x$lower))
  return(c(min(unlist(d), na.rm = TRUE), max(unlist(d), na.rm = TRUE)))
}

getYlab <- function(l) {
  names <- unlist(lapply(l, FUN = function(x) x$name))
  return(do.call("paste", c(as.list(names), sep = ", ")))
}

getLegend <- function(z) {
  x <- z$input
  l0 <- NULL
  if (!is.null(z$cvMSE)) {
    l0 <- paste0("LOO MSE = ", signif(z$cvMSE, 4), ", ")
  }
  if (!is.null(z$optim.CV.MSE)) {
    l0 <- paste0(l0, z$nFold, " fold ", z$gapCV, " gap MSE = ", signif(z$optim.CV.MSE, 4), ", ")
  }
  if (!is.null(z$optim.CV.MAE)) {
    l0 <- paste0(l0, z$nFold, " fold ", z$gapCV, " gap MAE = ", signif(z$optim.CV.MAE, 4), ", ")
  }

  if (length(x$lambdas) > 0) {
    l <- "Lambdas ="
    for (p in x$lambdas) {
      l <- paste(l, " (", paste(signif(p$lambdas, 3), collapse = ","), ")", sep = "")
    }
  } else {
    l <- NULL
  }

  return(paste0(l0, l))
}

createLayoutMatrix <- function(dataPanels, predictorPanels, randomPanels, forecastPanels, rHeader = 1, r = 3) {
  nPanels <- max(unlist(predictorPanels), dataPanels, randomPanels, forecastPanels)
  i <- 1
  v <- rep(i, rHeader)
  i <- i + 1
  for (k in seq_len(nPanels)) {
    v <- c(v, rep(i, r))
    i <- i + 1
  }
  return(as.matrix(v))
}

getDataToPlot <- function(scr, x, dataPanels, predictorPanels, randomPanels, forecastPanels, dataColor, predictorColors, randomColor, forecastColor) {
  toPlot <- list()
  j <- 1
  for (k in seq_along(predictorPanels)) {
    if (scr %in% predictorPanels[[k]] && !is.null(x$output$predictors[[k]]$upper)) {
      for (l in rev(seq_len(ncol(x$output$predictors[[k]]$upper)))) {
        toPlot[[j]] <- list(
          upper = x$output$predictors[[k]]$upper[, l],
          lower = x$output$predictors[[k]]$lower[, l],
          type = "polygon", col = "grey", border = "darkgrey", name = NULL
        )
        j <- j + 1
      }
    }
  }
  if (scr %in% forecastPanels && !is.null(x$output$forecast$upper)) {
    for (l in rev(seq_len(ncol(x$output$forecast$upper)))) {
      toPlot[[j]] <- list(
        upper = x$output$forecast$upper[, l],
        lower = x$output$forecast$lower[, l],
        type = "polygon", col = "grey", border = "darkgrey", name = NULL
      )
      j <- j + 1
    }
  }
  if (scr %in% dataPanels) {
    toPlot[[j]] <- list(data = x$input$data, type = "l", col = dataColor, name = "Observed")
    j <- j + 1
  }
  if (scr %in% randomPanels) {
    toPlot[[j]] <- list(data = x$output$random$data, type = "h", col = randomColor, name = "Random")
    j <- j + 1
  }
  for (k in seq_along(predictorPanels)) {
    if (scr %in% predictorPanels[[k]]) {
      toPlot[[j]] <- list(data = x$output$predictors[[k]]$data, type = "l", col = predictorColors[k], name = x$input$predictors[[k]]$name)
      j <- j + 1
    }
  }
  if (scr %in% forecastPanels) {
    toPlot[[j]] <- list(data = x$output$forecast$data, type = "l", col = forecastColor, name = "Fit/Forecast")
    j <- j + 1
  }
  return(toPlot)
}

#' @name plot.STR
#' @rdname plot.STR
#'
#' @title Plots the results of decomposition
#' @description \code{plot.STR} plots results of STR decomposition.
#' @seealso \code{\link{STRmodel}}, \code{\link{RSTRmodel}}, \code{\link{STR}}, \code{\link{AutoSTR}}
#' @param x Result of STR decomposition.
#' @param xTime Times for data to plot.
#' @param dataPanels Vector of panel numbers in which to plot the original data. Set to \code{NULL} to not show data.
#' @param predictorPanels A list of vectors of numbers where every such vector describes which panels should be used for plotting the corresponding predictor.
#' @param randomPanels Vector of panel numbers in which to plot the residuals.  Set to \code{NULL} to not show residuals.
#' @param forecastPanels Vector of panel numbers in which to plot the fit/forecast.  Set to \code{NULL} to not show forecasts.
#' @param dataColor Color to plot data.
#' @param predictorColors Vector of colors to plot components corresponding to the predictors.
#' @param randomColor Color to plot the residuals.
#' @param forecastColor Color to plot the fit/forecast.
#' @param vLines Vector of times where vertical lines will be plotted.
#' @param xlab Label for horizontal axis.
#' @param main Main heading for plot.
#' @param showLegend When \code{TRUE} (default) legend is shown at top of plot.
#' @param ... Other parameters to be passed directly to plot and lines functions in the implementation.
#' @author Alexander Dokumentov
#' @examples
#' \donttest{
#' fit <- AutoSTR(log(grocery))
#' plot(fit, forecastPanels = 0, randomColor = "DarkGreen", vLines = 2000:2010, lwd = 2)
#' }
#' @method plot STR
#' @export

plot.STR <- function(x, xTime = NULL, dataPanels = 1,
                     predictorPanels = as.list(seq_along(x$output$predictors)),
                     randomPanels = length(x$output$predictors) + 1,
                     forecastPanels = length(x$output$predictors) + 2,
                     dataColor = "black",
                     predictorColors = rep("red", length(x$output$predictors)),
                     randomColor = "red",
                     forecastColor = "blue",
                     vLines = NULL,
                     xlab = "Time",
                     main = ifelse(x$method %in% c("STR", "STRmodel"), "STR decomposition", "Robust STR decomposition"),
                     showLegend = TRUE, ...) {
  if (is.null(xTime)) {
    xTime <- as.vector(time(x$input$data))
  }
  if (length(x$input$data) != length(xTime)) {
    stop("Lengths of x and xTime should be same.")
  }
  op <- par(no.readonly = TRUE) # Resets parameters to the default state
  on.exit(par(op))

  lm <- createLayoutMatrix(dataPanels, predictorPanels, randomPanels, forecastPanels)
  layout(lm)
  par(mar = c(0, 4, 0, 0.5), oma = c(4.5, 0, 2, 0))
  plot.new()
  if (showLegend) {
    legendtext <- getLegend(x)
    if (!is.null(legendtext)) {
      legend("topleft", horiz = FALSE, bty = "n", legend = legendtext)
    }
  }

  nPanels <- max(unlist(predictorPanels), dataPanels, randomPanels, forecastPanels)
  for (scr in 1:nPanels) {
    toPlot <- getDataToPlot(scr, x, dataPanels, predictorPanels, randomPanels, forecastPanels, dataColor, predictorColors, randomColor, forecastColor)
    ylim <- getLimits(toPlot)
    ylab <- getYlab(toPlot)
    plot(xTime, x$input$data, ylab = ylab, type = "n", ylim = ylim, xaxt = "n", ...)
    Axis(x = xTime, side = 1, labels = scr == nPanels)
    abline(h = 0, col = "grey")
    if (!is.null(vLines)) {
      abline(v = vLines, col = "grey", ...)
    }
    for (p in toPlot) {
      if (p$type == "polygon") {
        polygon(c(xTime, rev(xTime)), c(p$upper, rev(p$lower)), col = p$col, border = p$border)
      } else {
        lines(xTime, p$data, col = p$col, type = p$type, ...)
      }
    }
  }
  mtext(xlab, side = 1, outer = TRUE, line = 2.5, cex = 0.9)
  mtext(main, side = 3, outer = TRUE)
}

Try the stR package in your browser

Any scripts or data that you put into this service are public.

stR documentation built on Sept. 11, 2024, 5:39 p.m.