Nothing
#' Test if the object is a hybridModel object
#'
#' Test if the object is a \code{hybridModel} object.
#'
#' @export
#' @param x the input object.
#' @return A boolean indicating if the object is a \code{hybridModel} is returned.
#'
is.hybridModel <- function(x) { # nolint
inherits(x, "hybridModel")
}
#' Extract Model Fitted Values
#'
#' Extract the model fitted values from the \code{hybridModel} object.
#'
#' @param object the input hybridModel.
#' @param individual if \code{TRUE}, return the fitted values of the component models instead
#' of the fitted values for the whole ensemble model.
#' @param ... other arguments (ignored).
#' @seealso \code{\link{accuracy}}
#' @return The fitted values of the ensemble or individual component models.
#' @export
#'
fitted.hybridModel <- function(object,
individual = FALSE,
...) {
chkDots(...)
if (individual) {
results <- list()
for (model in object$models) {
results[[model]] <- fitted(object[[model]])
}
return(results)
}
return(object$fitted)
}
#' Extract Model Residuals
#'
#' Extract the model residuals from the \code{hybridModel} object.
#' @export
#' @param object The input hybridModel.
#' @param individual If \code{TRUE}, return the residuals of the component models instead
#' of the residuals for the whole ensemble model.
#' @param ... Other arguments (ignored).
#' @seealso \code{\link{accuracy}}
#' @return The residuals of the ensemble or individual component models.
#'
residuals.hybridModel <- function(object,
individual = FALSE,
...) {
chkDots(...)
if (individual) {
results <- list()
for (model in object$models) {
results[[model]] <- residuals(object[[model]])
}
return(results)
}
return(object$residuals)
}
#' Accuracy measures for hybridModel objects
#'
#' Accuracy measures for hybridModel
#' objects.
#'
#' Return the in-sample accuracy measures for the component models of the hybridModel
#'
#' @param object the input hybridModel.
#' @param individual if \code{TRUE}, return the accuracy of the component models instead
#' of the accuracy for the whole ensemble model.
#' @param f Deprecated. Please use `object` instead.
#' @param ... other arguments (ignored).
#' @seealso \code{\link[forecast]{accuracy}}
#' @return The accuracy of the ensemble or individual component models.
#' @export
#'
#' @author David Shaub
#'
accuracy.hybridModel <- function(object, # nolint
individual = FALSE,
...,
f = NULL) {
chkDots(...)
if (!is.null(f)) {
warning("Using `f` as the argument for `accuracy()` is deprecated.",
"Please use `object` instead.")
object <- f
}
if (individual) {
results <- list()
for (model in object$models) {
results[[model]] <- forecast::accuracy(object[[model]])
}
return(results)
}
return(forecast::accuracy(object$fitted, getResponse(object)))
}
#' Accuracy measures for cross-validated time series
#'
#' Returns range of summary measures of the cross-validated forecast accuracy
#' for \code{cvts} objects.
#'
#' @param object a \code{cvts} objected created by \code{\link{cvts}}.
#' @param f Deprecated. Please use `object` instead.
#' @param ... other arguments (ignored).
#'
#' @details
#' Currently the method only implements \code{ME}, \code{RMSE}, and \code{MAE}. The accuracy
#' measures \code{MPE}, \code{MAPE}, and \code{MASE} are not calculated. The accuracy
#' is calculated for each forecast horizon up to \code{maxHorizon}
#' @export
#' @author David Shaub
#'
accuracy.cvts <- function(object, # nolint
...,
f = NULL) {
chkDots(...)
if (!is.null(f)) {
warning("Using `f` as the argument for `accuracy()` is deprecated.",
" Please use `object` instead.")
object <- f
}
ME <- colMeans(object$residuals) # nolint
RMSE <- apply(object$residuals, MARGIN = 2, # nolint
FUN = function(x) sqrt(sum(x ^ 2) / length(x)))
MAE <- colMeans(abs(object$residuals)) # nolint
results <- data.frame(ME, RMSE, MAE)
rownames(results) <- paste("Forecast Horizon ", rownames(results))
# MASE TODO
# Will require actual/fitted/residuals
return(results)
}
#' Print a summary of the hybridModel object
#'
#' @param x the input \code{hybridModel} object.
#' @details Print the names of the individual component models and their weights.
#'
#'
summary.hybridModel <- function(x) {
print(x)
}
#' Print information about the hybridModel object
#'
#' Print information about the \code{hybridModel} object.
#'
#' @param x the input \code{hybridModel} object.
#' @param ... other arguments (ignored).
#' @export
#' @details Print the names of the individual component models and their weights.
#'
print.hybridModel <- function(x,
...) {
chkDots(...)
cat("Hybrid forecast model comprised of the following models: ")
cat(x$models, sep = ", ")
cat("\n")
for (model in x$models) {
cat("############\n")
cat(model, "with weight", round(x$weights[model], 3), "\n")
}
}
#' Plot the component models of a hybridModel object
#'
#' Plot a representation of the hybridModel.
#' @param x an object of class hybridModel to plot.
#' @param ggplot should the \code{\link{autoplot}} function be used (when available) for the plots?
#' @param ... other arguments passed to \link{plot}.
#' @importFrom ggplot2 autoplot ggplot
plotModelObjects <- function(x,
ggplot,
...) {
chkDots(...)
plotModels <- x$models[x$models != "stlm" & x$models != "nnetar"]
for (i in seq_along(plotModels)) {
# bats, tbats, and nnetar aren't supported by autoplot
if (ggplot && !(plotModels[i] %in% c("tbats", "bats", "nnetar"))) {
autoplot(x[[plotModels[i]]])
} else if (!ggplot) {
plot(x[[plotModels[i]]])
}
}
}
#' Plot the fitted values of a hybridModel object
#'
#' Plot a fitted values of the hybridModel.
#' @param x an object of class hybridModel to plot.
#' @param ggplot should the \code{\link{autoplot}} function be used (when available) for the plots?
#' @param ... other arguments passed to \link{plot}.
#' @importFrom ggplot2 ggplot aes geom_line scale_y_continuous
plotFitted <- function(x,
ggplot,
...) {
chkDots(...)
plotModels <- x$models
if (ggplot) {
plotFrame <- data.frame(matrix(0, nrow = length(x$x), ncol = 0))
for (i in plotModels) {
plotFrame[i] <- fitted(x[[i]])
}
names(plotFrame) <- plotModels
plotFrame$date <- as.Date(time(x$x))
# Appease R CMD check for undeclared variable
variable <- NULL
value <- NULL
# If anyone knows a cleaner way to transform this "wide" data to "long" data for plotting
# with ggplot2 without using additional packages, let me know.
pf <- matrix(as.matrix(plotFrame[, plotModels]), ncol = 1)
pf <- data.frame(date = plotFrame$date,
variable = factor(rep(plotModels,
each = nrow(plotFrame)),
levels = plotModels),
value = pf)
plotFrame <- pf[order(pf$variable, pf$date), ]
ggplot(data = plotFrame,
aes(x = date, y = as.numeric(value), col = variable)) +
geom_line() + scale_y_continuous(name = "y")
} else {
# Set the highest and lowest axis scale
ymax <- max(sapply(plotModels,
FUN = function(i) max(fitted(x[[i]]), na.rm = TRUE)))
ymin <- min(sapply(plotModels,
FUN = function(i) min(fitted(x[[i]]), na.rm = TRUE)))
range <- ymax - ymin
plot(x$x, ylim = c(ymin - 0.05 * range, ymax + 0.25 * range), ...)
for (i in seq_along(plotModels)) {
lines(fitted(x[[plotModels[i]]]), col = i + 1)
}
legend("top", plotModels, fill = 2:(length(plotModels) + 1), horiz = TRUE)
}
}
#' Plot a hybridModel object
#'
#' Plot a representation of the hybridModel.
#'
#' @method plot hybridModel
#' @import forecast
#' @param x an object of class hybridModel to plot.
#' @param type if \code{type = "fit"}, plot the original series and the individual fitted models.
#' If \code{type = "models"}, use the regular plot methods from the component models, i.e.
#' \code{\link[forecast]{plot.Arima}}, \code{\link[forecast]{plot.ets}},
#' \code{\link[forecast]{plot.tbats}}. Note: no plot
#' methods exist for \code{nnetar} and \code{stlm} objects, so these will not be plotted with
#' \code{type = "models"}.
#' @param ggplot should the \code{\link{autoplot}} function
#' be used (when available) for the plots?
#' @param ... other arguments passed to \link{plot}.
#' @seealso \code{\link{hybridModel}}
#' @return None. Function produces a plot.
#'
#' @details For \code{type = "fit"}, the original series is plotted in black.
#' Fitted values for the individual component models are plotted in other colors.
#' For \code{type = "models"}, each individual component model is plotted. Since
#' there is not plot method for \code{stlm} or \code{nnetar} objects, these component
#' models are not plotted.
#' @examples
#' \dontrun{
#' hm <- hybridModel(woolyrnq, models = "aenst")
#' plot(hm, type = "fit")
#' plot(hm, type = "models")
#' }
#' @export
#'
#' @author David Shaub
plot.hybridModel <- function(x,
type = c("fit", "models"),
ggplot = FALSE,
...) {
type <- match.arg(type)
chkDots(...)
if (type == "fit") {
plotFitted(x = x, ggplot = ggplot)
} else if (type == "models") {
plotModelObjects(x = x, ggplot = ggplot)
}
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.