Skip to content

scoringutils

2.3.0Package record

Utilities for Scoring and Assessing Predictions

1packages dependsuggested by 4
16.3Kdownloads / year
99.2%test coverage
13/13flavors OK

Overview

About

Facilitate the evaluation of forecasts in a convenient framework based on data.table. It allows user to to check their forecasts and diagnose issues, to visualise forecasts and missing data, to transform data before scoring, to handle missing forecasts, to aggregate scores, and to visualise the results of the evaluation. The package mostly focuses on the evaluation of probabilistic forecasts and allows evaluating several different forecast types and input formats. Find more information about the package in the Vignettes as well as in the accompanying paper, doi:10.48550/arXiv.2205.07090.

Changes in 2.3.0

This release adds tools for handling missing forecasts (filter_scores(), impute_missing_scores()), a new plot_discrimination() for binary forecasts, and a much faster get_pairwise_comparisons(). It also fixes a number of bugs, several of which silently produced wrong scores. Many of these fixes mean that invalid input which was previously accepted now raises an error. Please read the "Breaking changes" section below if you are upgrading.

Breaking changes

The following changes may cause code that ran with scoringutils 2.2.0 to fail or behave differently. Most of them turn input that previously gave wrong or corrupted results, often silently, into an error.

  • as_forecast_<type>() functions now error when asked to rename a column onto a name that already exists in the data, for example as_forecast_binary(data, predicted = "prob") when data also has a predicted column. Previously this silently created a forecast object with duplicate column names, which passed validation and was then scored on the wrong column. assert_forecast() now also rejects data with duplicate column names. To fix affected code, remove or rename the stale column before calling as_forecast_<type>() (#1199).
  • Forecast validation now errors when the same forecast unit has conflicting observed values. Previously, this passed validation for quantile, sample, nominal, ordinal and multivariate sample forecasts, and score() silently returned multiple, wrong score rows for a single forecast. This usually means that a column that distinguishes forecasts (e.g. the target type) is missing from the data, or was dropped via the forecast_unit argument. Check the forecast unit with get_forecast_unit() and add the missing column (#1201).
  • summarise_scores() now errors when by contains a metric column (e.g. by = c("model", "wis")). Previously, this silently returned an unsummarised table with duplicate column names. Remove the metric column from by (#1204).
  • summarise_scores() now errors with a clear message when there are no score columns to summarise (e.g. because every metric in score() warned and returned nothing). Previously, it returned a data.table with duplicate column names (#1179).
  • get_pairwise_comparisons() and add_relative_skill() now error when the scores contain more than one distinct score per forecast unit and comparator. Previously, such conflicting rows were silently included in the comparison. Exact duplicate rows are still dropped. Remove the conflicting rows, or summarise the scores to one row per forecast unit and comparator first (#1221).
  • logs_categorical() now errors when predicted has more or fewer columns than there are factor levels. Previously, this was only checked for a single observation. With several observations, extra columns were silently scored meaninglessly and missing columns gave an uninformative "subscript out of bounds" error. score() is unaffected. rps_ordinal(), which already errored on such input, now gives a clearer error (#1200).
  • as_forecast_sample(), as_forecast_quantile() and as_forecast_multivariate_sample() now error at validation time when observed or predicted are not numeric. Previously, the failure only surfaced later inside score(), as one warning per metric and an effectively empty scores table. Convert observed and predicted to numeric first (#1211).
  • assert_forecast() for nominal and ordinal forecasts now returns invisible(NULL), as documented and as for all other forecast types. Previously, it visibly returned the forecast object. Code that used the return value should use the forecast object directly (#1195).
  • get_duplicate_forecasts() has a new type argument before counts. Code that passed counts by position must now name it, e.g. get_duplicate_forecasts(data, counts = TRUE) (#888).
Show all changes in 2.3.0Hide the rest of the changes in 2.3.0
  • scoringutils now requires data.table 1.17.0 or later (previously 1.16.0) (#935). It also newly depends on lifecycle (1.0.2 or later) (#888).

Deprecations

  • Calling get_duplicate_forecasts() on a plain data.frame without specifying type is deprecated and now warns. It falls back to guessing type-specific columns from their names. Pass type (e.g. type = "quantile"), or call it on a forecast object (#888).

New features

  • Added filter_scores() and impute_missing_scores() for handling missing forecasts before summarisation. filter_scores() removes target combinations with insufficient model coverage, while impute_missing_scores() fills in missing scores using configurable strategies (worst, mean, NA, or reference model). Both take a strategy function: filter_to_intersection() and filter_to_include() for filtering, and impute_worst_score(), impute_mean_score(), impute_na_score() and impute_model_score() for imputation. Custom strategies can be supplied too. See vignette("handling-missing-forecasts") for details (#1122).
  • Added plot_discrimination() to visualise the discrimination ability of binary forecasts by plotting the distribution of predicted probabilities, stratified by the observed outcome. The function requires a forecast_binary object (created with as_forecast_binary()) (#942).
  • Added get_forecast_type_ids(), an S3 generic that returns the columns (beyond the forecast unit) that identify a unique row for each forecast type. get_duplicate_forecasts() now uses it, and gains a type argument (e.g. type = "quantile") for use on plain data.frames (#888).
  • get_pairwise_comparisons(), and therefore add_relative_skill(), is now substantially faster and uses much less memory. Scores are pivoted once into a forecast unit by comparator matrix instead of being merged separately for every pair of comparators. Results are unchanged (#1221, thanks to @annakrystalli for the analysis and prototype).
  • add_relative_skill() no longer runs a statistical test for each pair of comparators by default, as it does not return the resulting p-values. This removes unnecessary computation and spurious warnings from wilcox.test() when scores are tied. Relative skill scores are unchanged. test_type is now an explicit argument with default NULL, and a test can still be requested through it (#1222, thanks to @annakrystalli).

Bug fixes

  • Fixed wis(), interval_score() and quantile_score(weigh = FALSE) returning NaN for forecasts that include the quantile levels 0 and 1 (which form a 100% prediction interval). Scores are now finite when the observation falls inside the interval, restoring the identity between the WIS and the mean of the quantile scores. The unweighted scores are Inf when the observation falls outside a 100% prediction interval (#1202).
  • Fixed interval_coverage() erroring on quantile levels generated with seq() (e.g. seq(0.05, 0.95, 0.05)), because quantile levels were matched with an exact floating point comparison. They are now rounded to 10 decimal places before matching, consistent with the rest of the package (#1202).
  • Fixed as_forecast_quantile() for sample-based forecasts producing silently wrong quantiles, or erroring, when probs was not symmetric around 0.5 (e.g. probs = 0.4 or probs = c(0.1, 0.2)). Quantiles are now computed at exactly the requested probs (deduplicated), and missing or out-of-range probs produce a clear error (#1196).
  • Fixed summarise_scores() also summarising columns whose names merely contain a metric name. Metric columns are now matched by exact name rather than by a regex partial match (#1179).
  • Fixed bias_quantile() returning wrong values when quantile levels were passed unsorted, because predictions and quantile levels became mispaired. Also fixed a crash when na.rm = TRUE removed all quantile levels on one side of the median. bias_quantile() now returns NA in this case, consistent with na.rm = FALSE (#1198).
  • Fixed bias_sample(), ae_median_sample(), se_mean_sample() and mad_sample() mishandling the documented input for a single observation (a scalar observed with a vector of samples as predicted): ae_median_sample() and se_mean_sample() silently returned wrong results, while bias_sample() and mad_sample() errored. All sample metrics now treat this input as one forecast with N samples, consistent with crps_sample(). Also corrected the integer bias formula in the bias_sample() documentation (the code was correct) (#1197).
  • Fixed rps_ordinal() and logs_categorical() returning wrong scores when called directly with a predicted_label that was not in the order of the factor levels. Scores are now invariant to how the columns of predicted are labelled. Forecasts scored via score() were unaffected (#1200).
  • as_forecast_binary(), assert_forecast(), brier_score(), logs_binary() and score() for binary forecasts now warn when the levels of observed are c("1", "0") or c("TRUE", "FALSE"). Predictions are interpreted as the probability of the second level, so with these levels they were silently read as the probability of "0" or "FALSE" (#763).
  • Fixed get_pit_histogram() for quantile-based forecasts: it now shows its full warning message and actually falls back to the quantiles present in the forecast when requested quantiles are missing, instead of returning an empty or incorrect result. The rounding warning in as_forecast_quantile() now correctly states that quantile levels are rounded to 9 digits (#1211).
  • Fixed forecast and scores objects printing spuriously when modified in place with :=, and added a print.scores() method. Subsetting a forecast object with [ now validates the result regardless of its size (previously only subsets with more than 30 rows were checked), so invalid subsets of small forecast objects now warn (#935).
  • Fixed the error message of assert_forecast() for incomplete nominal and ordinal forecasts, which named the first *complete* forecast instead of the first incomplete one (#1195).

Documentation

  • Added a more descriptive explanation of the use of energy and variogram scores in the vignette "Scoring multivariate forecasts", including how to pool over forecast horizons from a single origin and a multi-model comparison. Added a note explaining where these scores cannot be applied to quantile forecasts (#1193).
  • Removed the deprecated vignettes Deprecated-functions and Deprecated-visualisations. The code for removed functions (plot_predictions(), make_NA(), plot_ranges(), plot_score_table(), merge_pred_and_obs()) can still be found in the git history (#1158).

Internal changes

  • Added an internal helper prepare_forecast_for_scoring() that consolidates the input preparation steps previously duplicated across the score() methods: cleaning the forecast, validating the metrics and converting to a plain data.table, plus determining the forecast unit for the methods that need it (#941).
  • Updated the documentation to roxygen2 8.1.0 and fixed an R CMD check NOTE on R-devel (#1230).

From NEWS.md in the release

Install

Health

CRAN checks
13OK
Slowest check: 7.5 min · r-oldrel-windows-x86_64
Status changes
  • OK13 OK2026-09-30
  • NOTE12 OK, 1 NOTE2026-07-11
  • OK14 OK2026-03-19
  • ERROR13 OK, 1 ERROR2026-03-12
  • OK14 OK2026-03-10
Advisories

none known

Documentation

In release 2.3.0
READMEYes · 1,076 wordsVignettesYes · 3 · dynamicNEWSYes · 67% structured · mentions 2.3.0Citation fileYes · cites a publicationWebsiteYes · pkgdown
Cites a JSS article
Help pages
145 (38 internal)includes a package overview page
Examples that run
98%61 run in a plain check · 1 never run
Exported functions with examples
78%
Documented parameters
99%
Return-value docs
95%
Help pages citing references
12%

Downloads

16.3K
CRAN downloads in the past year
Rank #3,214 · ~45/day · ~1.4K/mo
Daily download trend is not available in this view yet.
1.8K30 days
3.6K90 days
16.3K1 year
Compare downloads with other packages →
Also on174 r2u2 autocran125 c2d4u

Repository

64Stars
24Forks
94Open issues
3Open PRs
11Releases
2,962Commits
20Commit identities
forecast-evaluationforecastingr-package
2,962 commits · Last activity 2026-09-27 · 0% stars, 30d · The default branch showed an older version (2.2.0.9000) than CRAN on 2026-10-18 · Discussions: 12 posts
Responsiveness
How these are sampled
PRs merged (all time)
85%
Median days to close, 50 most recently updated closed issues
80
Median days to close, 50 most recently updated closed PRs
54

Stars over time

2026-07-14 · 632026-08-23 · 64
PracticesBeta

15 development-tooling and community-health practices detected across 7 families in the upstream repository

Checks run against github.com/epiforecasts/scoringutils on 2026-10-18.

Continuous integration (2)
GitHub ActionsR CMD check workflow

The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel

Governance and community (3)
Code of conductContributing guidePR template
Docs source (4)
README.Rmdpkgdown

GitHub Pages site last deployed 2026-09-27 · The repository has a site deploy workflow

pkgdown site last built 2026-04-05, before release 2.3.0 (2026-09-27)

Coverage (1)
Coverage reporting
Show all practicesHide 3 practices
Reproducibility and dev environment (1)
Dev Container
Automation and maintenance (1)
Dependabot
Lint, format, editor (3)
lintrLint workflowRStudio project
How this is detected·Detection ruleset v3 (2026-09-26)
AI coding toolsBeta

This repository shows signs of AI coding tools.

  • Claude Codefirst seen 2026-02-01
    Named in .Rbuildignore: .claude
    Named in .gitignore: .claude
    Pull request it wrote: opened by a project member
    Commits: at least 71 crediting it in the message
Models named in its commits
  • Claude Opus 4.630 commits · Feb to Apr 2026
  • Claude Fable 523 commits · Jul 2026
  • Claude Opus 5.55 commits · Sep 2026
  • Claude Sonnet 55 commits · Sep 2026
  • Claude Fable 5.14 commits · Sep 2026

2 more models not listed.

Counts are commits, not lines of code. Commits by a tool's accounts count once across all of its accounts. Commits crediting it are the largest count among its credit lines, a minimum.How this is detected·Detection ruleset v4 (updated 2026-09-27)

Dependencies

Declared dependencies
14 external dependencies (excludes base and recommended)

Installing scoringutils adds 30 packages (17 with compiled code, 25 MB of source tarballs). Heaviest: ggplot2 6.0 MB, data.table 5.7 MB, Rcpp 1.8 MB.

Depends (1)
R >= 4.1
LinkingTo (0)
none
Enhances (0)
none
Reverse dependencies
1direct
1indirect
Imports 1
Suggested by 4
Depends, Imports or LinkingTo, most downloaded first
Suggests, most downloaded first

Datasets

People & History

People (8)
Author, Maintainer since 0.1.0 (2020)
Author · added in 2.0.0
Author · added in 1.0.0
Contributor · added in 2.0.0
Contributor · added in 2.0.0
Contributor · added in 2.0.0
Contributor · added in 2.0.0
Listed in earlier versions (4)
Show 4 peopleHide 4 people
Sophie Meakins
no longer listed · 0.1.0 to 0.1.7.2
no longer listed · 0.1.0 to 0.1.7.2
no longer listed · 0.1.0 to 0.1.7.2
no longer listed · 0.1.0 to 0.1.7.2
Releases (14)

Pick two releases to compare their code metrics.

  • 2.3.0Latest
    record
    2026-09-27 · current release · diff ↗ ·
    added 10 exports
    filter_scores, filter_to_include, filter_to_intersection, get_forecast_type_ids, impute_mean_score, impute_missing_scores, impute_model_score, impute_na_score, impute_worst_score, plot_discrimination
  • R
    R 4.6.0 released · 2026-04-24
  • 2.2.0
    record
    2026-04-05 · diff ↗ ·
    added 8 exports
    as_forecast_multivariate_point, as_forecast_multivariate_sample, energy_score_multivariate, get_grouping, is_forecast_multivariate_point, is_forecast_multivariate_sample, variogram_score_multivariate, variogram_score_multivariate_point
  • 2.1.2
    record
    2025-08-25 · diff ↗
  • 2.1.1
    record
    2025-06-26 · diff ↗
  • R
    R 4.5.0 released · 2025-04-11
  • 2.1.0
    record
    2025-03-03 · diff ↗ ·
    removed 1 export
    logs_nominal
    added 4 exports
    as_forecast_ordinal, is_forecast_ordinal, logs_categorical, rps_ordinal
  • 2.0.0
    record
    2024-10-31 · diff ↗ ·
    removed 25 exports
    abs_error, add_coverage, avail_forecasts, available_metrics, bias_range, check_forecasts, correlation, find_duplicates, interval_score, make_NA, make_na, merge_pred_and_obs, pairwise_comparison, pit, pit_sample, plot_avail_forecasts, plot_correlation, plot_pairwise_comparison, plot_pit, plot_predictions, plot_ranges, plot_score_table, sample_to_quantile, set_forecast_unit, squared_error
    added 36 exports
    add_relative_skill, as_forecast_binary, as_forecast_nominal, as_forecast_point, as_forecast_quantile, as_forecast_sample, assert_forecast, dispersion_quantile, dispersion_sample, get_correlations, get_coverage, get_duplicate_forecasts, get_forecast_counts, get_forecast_unit, get_metrics, get_pairwise_comparisons, get_pit_histogram, interval_coverage, is_forecast, is_forecast_binary, is_forecast_nominal, is_forecast_point, is_forecast_quantile, is_forecast_sample, logs_nominal, new_forecast, overprediction_quantile, overprediction_sample, pit_histogram_sample, plot_correlations and 6 more
  • R
    R 4.4.0 released · 2024-04-24
  • 1.2.2
    record
    2023-11-29 · diff ↗ ·
    added 3 exports
    log_shift, set_forecast_unit, transform_forecasts
  • R
    R 4.3.0 released · 2023-04-21
  • 1.1.0
    record
    2023-01-30 · diff ↗
  • 1.0.1
    record
    2022-08-17 · diff ↗
  • 1.0.0
    record
    2022-05-13 · diff ↗ ·
    removed 29 exports
    bias, correlation_plot, crps, dss, eval_forecasts, interval_coverage, logs, mse, pit_df, pit_df_fast, quantile_bias, quantile_coverage, quantile_to_long, quantile_to_range, quantile_to_range_long, quantile_to_wide, range_long_to_quantile, range_long_to_wide, range_plot, range_to_quantile, range_wide_to_long, sample_to_range, sample_to_range_long, score_heatmap, score_table, sharpness, show_avail_forecasts, update_list, wis_components
    added 33 exports
    add_coverage, avail_forecasts, available_metrics, bias_quantile, bias_range, bias_sample, check_forecasts, correlation, crps_sample, dss_sample, find_duplicates, logs_binary, logs_sample, mad_sample, make_NA, make_na, pit_sample, plot_avail_forecasts, plot_correlation, plot_heatmap, plot_interval_coverage, plot_pit, plot_quantile_coverage, plot_ranges, plot_score_table, plot_wis, quantile_score, score, se_mean_sample, squared_error and 3 more
  • R
    R 4.2.0 released · 2022-04-22
  • 0.1.7.2
    record
    2021-07-21 · diff ↗
Show 5 earlier eventsHide 5 earlier events
  • 0.1.7
    record
    2021-07-14 · diff ↗ ·
    removed 1 export
    ae_median
    added 15 exports
    abs_error, ae_median_quantile, ae_median_sample, merge_pred_and_obs, pairwise_comparison, pit_df, pit_df_fast, plot_pairwise_comparison, quantile_to_range_long, range_long_to_quantile, range_long_to_wide, range_wide_to_long, sample_to_range_long, show_avail_forecasts, update_list
  • R
    R 4.1.0 released · 2021-05-18
  • 0.1.4
    record
    2020-11-17 · diff ↗ ·
    added 16 exports
    ae_median, correlation_plot, interval_coverage, plot_predictions, quantile_bias, quantile_coverage, quantile_to_long, quantile_to_range, quantile_to_wide, range_plot, range_to_quantile, sample_to_quantile, sample_to_range, score_heatmap, score_table, wis_components
  • 0.1.0
    record
    2020-06-14
  • R
    R 4.0.0 released · 2020-04-24

Package metadata

First published
2020-06-14
Total releases
14 / 6 yrs
License
MIT + file LICENSE OSI
Minimum R
≥ 4.1
Bundled data
683 KB / 8 files
Download size
4.4 MB
Appears in task views

Cite

Cite this package

Run in R for the authors' entry:

citation("scoringutils")

The package provides a citation file, so citation() returns the authors' own entry.

It points to 10.48550/arxiv.2205.07090, 10.18637/jss.v090.i12.

Cite the R Observatory

For a number measured here: a download total, a coverage figure, an archival date.

APA

Balamuta, J. J. (2026). R Observatory: Metrics for scoringutils version 2.3.0 [Data set]. HJJB, LLC. Data release v2026-10-20. https://doi.org/10.5281/zenodo.21843040

From data release v2026-10-20, which the citation names so these numbers can be found later. More on citing and the projects behind them.

Report a problem with this page →

Privacy choices

These apply to this browser and are stored on this device only. Nothing about your choice is sent to us.

Read the privacy policy