Skip to content

Missing type checks in sample/quantile validation and message/behaviour mismatches #1211

Description

@nikosbosse

Three related validation/message problems, verified against current main:

1. as_forecast_sample() / as_forecast_quantile() accept non-numeric observed/predicted

as_forecast_sample(data.frame(
  observed = as.character(c(5, 5, 5)),
  predicted = as.character(c(4, 5, 6)),
  sample_id = 1:3, model = "m1"
))

succeeds (returns a forecast_sample object). The failure only surfaces later in score(), as one warning per metric, e.g.:

! Computation for `crps` failed. Error: Assertion on 'observed' failed: Must be of type 'numeric', not 'character'.

and score() returns a 1-row table with only a model column. Identical behaviour for as_forecast_quantile() with character columns (8 per-metric warnings). By contrast, as_forecast_binary() and as_forecast_point() error immediately at validation time.

Cause: assert_forecast.forecast_sample() (R/class-forecast-sample.R:59-66) only checks sample_id column presence plus generic checks, and assert_forecast.forecast_quantile() (R/class-forecast-quantile.R:82-90) only asserts quantile_level is numeric — neither checks the types of observed/predicted, unlike the binary/point methods which call check_input_binary()/check_input_point(). The same gap exists in assert_forecast.forecast_multivariate_sample() (R/class-forecast-multivariate-sample.R:85-120); the multivariate point method already validates via check_input_point().

2. Quantile rounding warning says digits = 10 but code rounds to 9 digits

R/class-forecast-quantile.R:61-69: the warning emitted by as_forecast_quantile() for near-duplicate quantile levels says "we're going to run round(x, digits = 10)" but the code executes round(data$quantile_level, digits = 9). Behavioural proof: input level 0.9999999994 (representable at 10 digits) came out as 0.999999999 — 9-digit rounding was applied. The message also has an unclosed parenthesis: "(run diff(...) to see this.".

3. get_pit_histogram.forecast_quantile(): broken warning and fallback that never happens

R/class-forecast-quantile.R:249-254: cli_warn() is called with two unnamed strings, so the second sentence ("The PIT histogram will be based on the quantiles present in the forecast.") lands in rlang's class parameter instead of the message — the user only sees "Some requested quantiles are missing in the forecast." And the advertised fallback never happens:

  • get_pit_histogram(fq, num_bins = 7, by = "model") on example_quantile returns a 0-row data.table (all rows dropped by forecast[quantile_level %in% quantiles]).
  • Partially-present breaks = c(0.25, 0.33, 0.5) produces 4 "longer object length is not a multiple of shorter object length" warnings and silently wrong densities (values recycled, e.g. bin [0.25,0.33) density 4.59 for a bin with no coverage data).

Intended fix (maintainer decisions)

  1. Add checkmate::assert_numeric() checks for observed and predicted to the sample and quantile assert_forecast() methods, and extend the same check to the multivariate sample method (multivariate point is already covered).
  2. Fix the warning message to say digits = 9 (keep the code at 9 — rounding to 10 digits would fail to collapse diffs of exactly 1e-10) and close the dangling parenthesis.
  3. Fix the cli_warn() call so both lines display, and make the advertised fallback actually happen: keep the requested quantiles that are present in the forecast; if none besides 0/1 survive, fall back to all present quantiles. Compute diffs after this adjustment so bins/mids/densities stay aligned.

Part of the bug audit in #1189.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions