library(bayesRecon)
#' # ---- Example 1: base forecasts are given ----
# Create a minimal hierarchy with 2 bottom and 1 upper variable
A <- get_reconc_matrices(agg_levels = c(1, 2), h = 2)$A
# Set the parameters of the Gaussian base forecast distributions
mu1 <- 2
mu2 <- 4
muY <- 9
base_fc_mean <- c(muY, mu1, mu2) # vector of means
sigma1 <- 2
sigma2 <- 2
sigmaY <- 3
sigmas <- c(sigmaY, sigma1, sigma2)
base_fc_cov <- diag(sigmas^2) # covariance matrix
analytic_rec <- reconc_gaussian(A,
base_fc_mean = base_fc_mean,
base_fc_cov = base_fc_cov
)
bottom_mean_rec <- analytic_rec$bottom_rec_mean
bottom_cov_rec <- analytic_rec$bottom_rec_cov
# To obtain reconciled samples for the entire hierarchy, sample from the reconciled
# bottom distribution and then aggregate using A.
# Sample from the reconciled bottom-level Gaussian distribution
# First, compute the Cholesky decomposition of the reconciled covariance matrix:
chol_decomp <- chol(bottom_cov_rec)
# Then, sample from the standard normal distribution and apply the transformation:
Z <- matrix(stats::rnorm(n = 2000), nrow = 2)
B <- t(chol_decomp) %*% Z + matrix(rep(bottom_mean_rec, 1000), nrow = 2)
# Aggregate bottom samples to get upper samples, then stack
U <- A %*% B
Y_reconc <- rbind(U, B)
cat("Dimensions of reconciled samples (upper + bottom):", dim(Y_reconc), "\n")
# ---- Example 2: using residuals from fitted ETS models ----
# \donttest{
if (requireNamespace("forecast", quietly = TRUE)) {
# Simulate 2 bottom series from AR(1) processes
set.seed(1234)
n_obs <- 200
y1 <- arima.sim(model = list(ar = 0.8), n = n_obs)
y2 <- arima.sim(model = list(ar = 0.5), n = n_obs)
# Upper series is the sum of the two bottom series
y_upper <- y1 + y2
# Aggregation matrix A:
A <- matrix(c(1, 1), nrow = 1)
# Fit additive ETS models
fit1 <- forecast::ets(y1, additive.only = TRUE)
fit2 <- forecast::ets(y2, additive.only = TRUE)
fit_upper <- forecast::ets(y_upper, additive.only = TRUE)
# Point forecasts (h = 1):
fc1 <- forecast::forecast(fit1, h = 1)$mean
fc2 <- forecast::forecast(fit2, h = 1)$mean
fc_upper <- forecast::forecast(fit_upper, h = 1)$mean
base_fc_mean <- c(fc_upper, fc1, fc2)
# Residuals matrix (T x n, columns in same order as base_fc_mean)
res <- cbind(residuals(fit_upper),
residuals(fit1),
residuals(fit2))
# Reconcile (covariance estimated internally via Schafer-Strimmer)
result <- reconc_gaussian(A, base_fc_mean = base_fc_mean, residuals = res, return_upper = TRUE)
bottom_mean <- result$bottom_rec_mean
bottom_cov <- result$bottom_rec_cov
upper_mean <- result$upper_rec_mean
upper_cov <- result$upper_rec_cov
# Print reconciled means
cat("Reconciled bottom means:", round(bottom_mean, 3), "\n")
cat("Reconciled upper mean:", round(upper_mean, 3), "\n")
# Print 95% predictions intervals
cat("Reconciled bottom 95% prediction intervals:\n")
for (i in 1:length(bottom_mean)) {
lower <- bottom_mean[i] - 1.96 * sqrt(bottom_cov[i, i])
upper <- bottom_mean[i] + 1.96 * sqrt(bottom_cov[i, i])
cat(paste0("Bottom ", i, ": [", round(lower, 3), ", ", round(upper, 3), "]\n"))
}
cat("Reconciled upper 95% prediction interval:\n")
lower <- upper_mean - 1.96 * sqrt(upper_cov[1, 1])
upper <- upper_mean + 1.96 * sqrt(upper_cov[1, 1])
cat(paste0("Upper: [", round(lower, 3), ", ", round(upper, 3), "]\n"))
}
# }
Run the code above in your browser using DataLab