Summary
transform_forecasts(append = TRUE) fails on forecast_sample_multivariate objects due to a naming inconsistency between the class name and the constructor function.
The bug
The class is named forecast_sample_multivariate but the constructor is as_forecast_multivariate_sample (different word order). When transform_forecasts() with append = TRUE tries to reconstruct a valid forecast object after binding rows, it dynamically constructs the constructor name from the class:
# R/transform-forecasts.R, lines 161-164
fn_name <- paste0("as_forecast_", forecast_type)
fn <- get(fn_name)
out <- suppressWarnings(suppressMessages(do.call(fn, list(out))))
get_forecast_type() strips the forecast_ prefix from forecast_sample_multivariate, yielding sample_multivariate. So fn_name becomes as_forecast_sample_multivariate — but the actual constructor is as_forecast_multivariate_sample. The get() call fails with "object not found".
Naming comparison
| Class |
Constructor |
transform_forecasts looks for |
Match? |
forecast_quantile |
as_forecast_quantile |
as_forecast_quantile |
Yes |
forecast_sample |
as_forecast_sample |
as_forecast_sample |
Yes |
forecast_binary |
as_forecast_binary |
as_forecast_binary |
Yes |
forecast_sample_multivariate |
as_forecast_multivariate_sample |
as_forecast_sample_multivariate |
No |
Proposed fix
Rename the class from forecast_sample_multivariate to forecast_multivariate_sample so it matches the constructor as_forecast_multivariate_sample. This aligns the naming convention so that get_forecast_type() returns multivariate_sample and transform_forecasts() correctly constructs as_forecast_multivariate_sample.
Why it hasn't been caught
The test suite for transform_forecasts() (tests/testthat/test-transform-forecasts.R) only tests on forecast_quantile and forecast_binary objects — never on forecast_sample_multivariate.
Reprex
library(scoringutils)
# This will fail with: object 'as_forecast_sample_multivariate' not found
transform_forecasts(
example_multivariate_sample,
fun = log_shift,
offset = 1,
append = TRUE
)
Context
Discovered during planning for hubverse-org/hubEvals#94 (adding sample forecast scoring to hubEvals). hubEvals needs to work around this by blocking transform_append = TRUE for compound sample forecasts.
This was opened by a bot. Please ping @seabbs for any questions.
Summary
transform_forecasts(append = TRUE)fails onforecast_sample_multivariateobjects due to a naming inconsistency between the class name and the constructor function.The bug
The class is named
forecast_sample_multivariatebut the constructor isas_forecast_multivariate_sample(different word order). Whentransform_forecasts()withappend = TRUEtries to reconstruct a valid forecast object after binding rows, it dynamically constructs the constructor name from the class:get_forecast_type()strips theforecast_prefix fromforecast_sample_multivariate, yieldingsample_multivariate. Sofn_namebecomesas_forecast_sample_multivariate— but the actual constructor isas_forecast_multivariate_sample. Theget()call fails with "object not found".Naming comparison
transform_forecastslooks forforecast_quantileas_forecast_quantileas_forecast_quantileforecast_sampleas_forecast_sampleas_forecast_sampleforecast_binaryas_forecast_binaryas_forecast_binaryforecast_sample_multivariateas_forecast_multivariate_sampleas_forecast_sample_multivariateProposed fix
Rename the class from
forecast_sample_multivariatetoforecast_multivariate_sampleso it matches the constructoras_forecast_multivariate_sample. This aligns the naming convention so thatget_forecast_type()returnsmultivariate_sampleandtransform_forecasts()correctly constructsas_forecast_multivariate_sample.Why it hasn't been caught
The test suite for
transform_forecasts()(tests/testthat/test-transform-forecasts.R) only tests onforecast_quantileandforecast_binaryobjects — never onforecast_sample_multivariate.Reprex
Context
Discovered during planning for hubverse-org/hubEvals#94 (adding sample forecast scoring to hubEvals). hubEvals needs to work around this by blocking
transform_append = TRUEfor compound sample forecasts.This was opened by a bot. Please ping @seabbs for any questions.