Here is a reproducible example for what I think is a bug uncovered while developing forecasting evaluation course materials.
I had locally a copy of fabletools 0.8.0 and the website is running a cached version of 0.7.x and we were getting different results for a power-transformed (fourth-root, in this case) forecasts. Below is a minimal reproducible example using fabletools 0.8.0.
Note that at the end the fabletools_CRPS should agree with the sample_truth column and it does for the no transform and log transform but does not agree for the sqrt transform.
## Minimal reproducible example
##
## fabletools::CRPS() over-estimates CRPS for power-transformed
## (e.g. sqrt) forecast distributions.
## It is correct for untransformed (Normal) and log-transformed forecasts.
##
## Ground truth = CRPS of the SAME forecast distribution, estimated from its own
## samples via scoringRules::crps_sample().
suppressMessages({library(fable); library(tsibble); library(dplyr)})
set.seed(1)
n <- 100
y <- rnorm(n, mean = 2.5, sd = 0.35)^2 # simple, positive, right-skewed series
dat <- tsibble(t = seq_len(n), y = y, index = t)
obs <- 6 # value to score the 1-step forecast against
fit <- dat |> model(
none = RW(y), # Normal forecast (control)
log = RW(log(y)), # log transform (control)
sqrt = RW(sqrt(y)) # power transform (affected)
)
fc <- forecast(fit, h = 1)
res <- lapply(c("none", "log", "sqrt"), function(m) {
D <- fc |> filter(.model == m) |> pull(y) # length-1 distribution vector
set.seed(1)
data.frame(
model = m,
fabletools_CRPS = fabletools::CRPS(D, obs),
sample_truth = scoringRules::crps_sample(obs, distributional::generate(D, 1e6)[[1]])
)
})
res <- do.call(rbind, res); res$ratio <- res$fabletools_CRPS / res$sample_truth
print(res, digits = 4, row.names = FALSE)
#> model fabletools_CRPS sample_truth ratio
#> none 0.5790 0.5790 0.9999
#> log 0.5263 0.5258 1.0009
#> sqrt 2.8696 0.5418 5.2967
sessionInfo()
#> R version 4.4.3 (2025-02-28)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Sequoia 15.7.7
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.0
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: America/New_York
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] dplyr_1.2.0 tsibble_1.2.0 fable_0.5.0 fabletools_0.8.0
#>
#> loaded via a namespace (and not attached):
#> [1] gtable_0.3.6 compiler_4.4.3 vecvec_1.2.0
#> [4] tidyselect_1.2.1 reprex_2.1.1 Rcpp_1.1.1-1.1
#> [7] dichromat_2.0-0.1 tidyr_1.3.2 scales_1.4.0
#> [10] yaml_2.3.12 fastmap_1.2.0 ggplot2_4.0.2
#> [13] R6_2.6.1 generics_0.1.4 distributional_0.5.0
#> [16] knitr_1.51 MASS_7.3-65 ggtime_0.2.0.9000
#> [19] tibble_3.3.1 mixtime_0.2.0.9000 lubridate_1.9.5
#> [22] tzdb_0.5.0 RColorBrewer_1.1-3 pillar_1.11.1
#> [25] scoringRules_1.1.3 rlang_1.2.0 xfun_0.59
#> [28] S7_0.2.2 fs_2.1.0 otel_0.2.0
#> [31] timechange_0.4.0 cli_3.6.6 progressr_1.0.0
#> [34] withr_3.0.3 magrittr_2.0.5 digest_0.6.39
#> [37] grid_4.4.3 rstudioapi_0.19.0 lifecycle_1.0.5
#> [40] anytime_0.3.13 vctrs_0.7.1 evaluate_1.0.5
#> [43] glue_1.8.1 numDeriv_2016.8-1.1 farver_2.1.2
#> [46] purrr_1.2.0 rmarkdown_2.30 tools_4.4.3
#> [49] pkgconfig_2.0.3 htmltools_0.5.9
Created on 2026-07-16 with reprex v2.1.1
Here is a reproducible example for what I think is a bug uncovered while developing forecasting evaluation course materials.
I had locally a copy of fabletools 0.8.0 and the website is running a cached version of 0.7.x and we were getting different results for a power-transformed (fourth-root, in this case) forecasts. Below is a minimal reproducible example using fabletools 0.8.0.
Note that at the end the fabletools_CRPS should agree with the sample_truth column and it does for the no transform and log transform but does not agree for the sqrt transform.
Created on 2026-07-16 with reprex v2.1.1