% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/compute_on_forecast.R
\name{transform_forecast}
\alias{transform_forecast}
\title{Transform forecasts from model scale to data scale by simulation}
\usage{
transform_forecast(fc_object, trans_fun, nsim = 2000L, level = 95, y0 = 1)
}
\arguments{
\item{fc_object}{A \code{"forecast"} object (from the \pkg{forecast} package)
for a univariate time series, typically obtained via
\code{forecast::forecast()}.}

\item{trans_fun}{A function of the form \code{function(x, y0) ...}
that takes a numeric vector \code{x} on the model scale and a scalar
starting value \code{y0} on the output scale and returns a numeric vector
of the same length on the output scale.}

\item{nsim}{Integer; number of simulated future paths to use. Larger
values give smoother prediction intervals but take longer to compute.}

\item{level}{Numeric; prediction interval coverage in percent.}

\item{y0}{Numeric; starting value on the output scale used to
reconstruct the historical series from \code{fc_object$x}. For percentage
change models it is often natural to set \code{y0 = 1} and interpret
the resulting series as an index.}
}
\value{
A \code{"forecast"} object similar to \code{fc_object}, but with the components
\code{x}, \code{mean}, \code{lower}, and \code{upper} defined on the output (data) scale.
}
\description{
\code{transform_forecast()} takes a univariate time series forecast fitted on a
transformed (model) scale and produces a new forecast object on the
original data scale. This is done by simulating future paths on the
model scale, transforming each path with a user-supplied function, and
then computing pointwise means and prediction intervals on the
transformed scale.
}
\details{
The function assumes that \code{fc_object} is a \code{"forecast"} object as
produced by the \pkg{forecast} package, and that \code{fc_object$model}
supports \code{simulate()} with arguments \code{nsim} and \code{future}.

The transformation function \code{trans_fun} must have the form
\code{trans_fun(x, y0)}, where \code{x} is a numeric vector representing a path on
the model scale (for example log-values or percentage changes), and
\code{y0} is a scalar "starting value" on the output scale. The function must
return a numeric vector of the same length as \code{x} giving the
corresponding path on the output scale.

Internally, \code{transform_forecast()} first reconstructs a historical series on
the output scale by applying \code{trans_fun()} to \code{fc_object$x} with the
supplied \code{y0}. It then simulates \code{nsim} future paths from
\code{fc_object$model} on the model scale, transforms each path to the
output scale using \code{trans_fun()} with \code{y0} equal to the last value of
the reconstructed historical series, and finally computes the pointwise
mean and prediction intervals (of nominal coverage \code{level}) across
the simulated paths. The result is returned as a new \code{"forecast"} object
with \code{x}, \code{mean}, \code{lower}, and \code{upper} on the output scale.
}
\examples{
## Example 1: Log-transform of the Canadian lynx data
if (requireNamespace("forecast", quietly = TRUE)) {

  llynx   <- log(lynx)
  fit_log <- forecast::auto.arima(llynx)
  fc_log  <- forecast::forecast(fit_log, h = 20)
  forecast::autoplot(fc_log)
  ## transformation: log -> original scale
  trans_log <- function(z, y0) {
    exp(z)
  }
  fc_lynx <- transform_forecast(fc_log, trans_fun = trans_log,
                            nsim = 20, level = 95, y0 = 1)
  plot(fc_lynx)
  forecast::autoplot(fc_lynx) + ggplot2::theme_minimal()
}


\dontrun{
if (requireNamespace("forecast", quietly = TRUE)) {
## Example 2 (variation): CO2 series, log-transform
  lco2    <- log(co2)
  fit_co2 <- forecast::auto.arima(lco2)
  fc_log_co2 <- forecast::forecast(fit_co2, h = 24)
  forecast::autoplot(fc_log_co2)
  trans_log <- function(z, y0) exp(z)

  fc_co2 <- transform_forecast(fc_log_co2, trans_fun = trans_log,
                           nsim = 20, level = 95, y0 = 1)
  forecast::autoplot(fc_co2) + ggplot2::theme_minimal()
}

# ## Example 3: Percentage change in income (uschange$Income)
if (requireNamespace("forecast", quietly = TRUE) &&
    requireNamespace("fpp2", quietly = TRUE)) {
  income <- uschange[, "Income"]  # quarterly percentage changes (\%)

  ## transformation: pct change -> index with base 1
  trans_pct <- function(r, y0) {
    y0 * cumprod(1 + r / 100)
  }

  fit_pct <- forecast::auto.arima(income)
  fc_pct  <- forecast::forecast(fit_pct, h = 24)
  forecast::autoplot(fc_pct)
  fc_idx  <- transform_forecast(fc_pct, trans_fun = trans_pct,
                            nsim = 200, level = 95, y0 = 1)

  plot(fc_idx)
  forecast::autoplot(fc_idx) + ggplot2::theme_minimal()
 }
 }
 
}
\seealso{
\code{\link[forecast]{forecast}}, \code{\link[forecast]{auto.arima}},
\code{\link[stats]{simulate}}, \code{\link[stats]{ts}}.
}
