-
Notifications
You must be signed in to change notification settings - Fork 25
Add coverage deviation as a metric #417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
56 commits
Select commit
Hold shift + click to select a range
31271d3
Add new function, `interval_coverage_deviation_quantile()` - I know t…
nikosbosse 9c9f286
Create a new helper function to compute ranges of central prediction …
nikosbosse b883dd8
Update `metrics_quantile`
nikosbosse 7b62919
Small update to `metrics_quantile` + fixing a typo
nikosbosse c674764
update `ae_median_quantile()` and documentation associated to `wis()`…
nikosbosse 27d4a78
add input checks to `ae_median_sample()` and `se_mean_sample()`
nikosbosse e2618cd
Update documentation for `metrics_quantile` and remove # no lint from…
nikosbosse 2ef9a52
Correct error in ae_median_quantile, update data file and documentation
nikosbosse 7e635eb
Correct an issue with `pit()` where this still relies on the computat…
nikosbosse 77fcde4
commit previously forgotten change in `metrics_quantile`
nikosbosse 295eb51
Fix issues with ae_median_sample(), ae_median_quantile() and se_mean_…
nikosbosse 88fcdce
Change "interval_score" to "wis" as a metric name. Comment out code f…
nikosbosse 337ea1f
Replace score.scoringutils_quantile() with new function
nikosbosse 7e6dbe8
update available_metrics() to include wis and coverage_ values (this …
nikosbosse 08dab31
Update vignette to update / comment out code that cannot be run anymore
nikosbosse f4d5d43
Fix test for ae_median_sample()
nikosbosse 9607615
Update tests
nikosbosse c214ade
comment out / delete failing tests related to ranges in the output of…
nikosbosse 71d6d65
Delete old version of `score.score_quantile()`
nikosbosse 596dcee
improve the way that data.frames are split in `score()` to deal with …
nikosbosse 6989f5d
Add test file for binary metrics and input checks
nikosbosse 376de95
Remove comment (to be turned into an issue)
nikosbosse b13f00a
small fix in score.scoringutils_quantile to avoid a warning
nikosbosse 983c030
move tests around so they better correspond to file names used for ac…
nikosbosse c89b1f5
fix small test issues
nikosbosse cd0d154
Add input checks for quantile-based forecasts
nikosbosse 40807ad
remove old test for sharpness (test has been moved to test-metrics-sa…
nikosbosse fa3a7ab
move piece of code around within the metrics-quantile.R file (since m…
nikosbosse 0d42acc
Add more tests for quantile metrics
nikosbosse 32357f1
Rework existing `add_coverage()` function to work with raw forecasts
nikosbosse 1be9055
Update News
nikosbosse 8719dbe
Update `get_protetcted_columns()` with coverage columns
nikosbosse 1252e13
Update `quantile_to_interval.data.frame()` to work with NA values
nikosbosse 3af9fff
Don't remove NA values in `add_coverage()` anymore
nikosbosse 02c4b1c
Update `add_coverage` to store an attribute `metric_names` with the n…
nikosbosse b41d655
Update tests and code snippets to get stuff working again that was pr…
nikosbosse 79fc533
Automatic readme update
actions-user f7faff2
horrible, but working version of a refactoring of score.scoringutils_…
nikosbosse cb9bcbe
More elegant version, currently failing for sample-based forecasts be…
nikosbosse 102370d
Fix score.scoringutils_sample by using matrices
nikosbosse 004d2b8
move the expression into `apply_metrics()`
nikosbosse 7eb7c96
Update metrics_quantile (improved error handling + getting rid of `ru…
nikosbosse 6c213fc
Add global variable to fix failing test
nikosbosse 9705994
Create function to ensure an object is a data.table
nikosbosse afdd3ac
Simplify set_forcast_unit and ensure that it operates on a data.table
nikosbosse 218c01c
Make message in `check_columns_present` nicer
nikosbosse 21d887a
Reintroduce `run_safely()` into `metrics_quantile` - the alternative …
nikosbosse ebe3869
correct `check_columns_present()`
nikosbosse ba9adbf
Update `set_forecast_unit()` and add tests
nikosbosse be1f53c
Merge pull request #419 from epiforecasts/rework_ae_median
nikosbosse c6c2dfc
Merge pull request #421 from epiforecasts/rework-score.scoringutils_q…
nikosbosse 3928002
Merge pull request #422 from epiforecasts/expand-tests
nikosbosse b45ec5a
Merge pull request #423 from epiforecasts/expand-tests2
nikosbosse e3fcec3
Merge pull request #426 from epiforecasts/reword-add_coverage2
nikosbosse cc72c53
Merge pull request #430 from epiforecasts/create-apply-metrics
nikosbosse ad411da
Merge pull request #437 from epiforecasts/fix-set_forecast_unit
nikosbosse File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| #' @title Add Coverage Values to Quantile-Based Forecasts | ||
| #' | ||
| #' @description Adds interval coverage of central prediction intervals, | ||
| #' quantile coverage for predictive quantiles, as well as the deviation between | ||
| #' desired and actual coverage to a data.table. Forecasts should be in a | ||
| #' quantile format (following the input requirements of `score()`). | ||
| #' | ||
| #' **Interval coverage** | ||
| #' | ||
| #' Coverage for a given interval range is defined as the proportion of | ||
| #' observations that fall within the corresponding central prediction intervals. | ||
| #' Central prediction intervals are symmetric around the median and and formed | ||
| #' by two quantiles that denote the lower and upper bound. For example, the 50% | ||
| #' central prediction interval is the interval between the 0.25 and 0.75 | ||
| #' quantiles of the predictive distribution. | ||
| #' | ||
| #' The function `add_coverage()` computes the coverage per central prediction | ||
| #' interval, so the coverage will always be either `TRUE` (observed value falls | ||
| #' within the interval) or `FALSE` (observed value falls outside the interval). | ||
| #' You can summarise the coverage values to get the proportion of observations | ||
| #' that fall within the central prediction intervals. | ||
| #' | ||
| #' **Quantile coverage** | ||
| #' | ||
| #' Quantile coverage for a given quantile is defined as the proportion of | ||
| #' observed values that are smaller than the corresponding predictive quantile. | ||
| #' For example, the 0.5 quantile coverage is the proportion of observed values | ||
| #' that are smaller than the 0.5 quantile of the predictive distribution. | ||
| #' | ||
| #' **Coverage deviation** | ||
| #' | ||
| #' The coverage deviation is the difference between the desired coverage and the | ||
| #' actual coverage. For example, if the desired coverage is 90% and the actual | ||
| #' coverage is 80%, the coverage deviation is -0.1. | ||
| #' | ||
| #' @inheritParams score | ||
| #' @return a data.table with the input and columns "interval_coverage", | ||
| #' "interval_coverage_deviation", "quantile_coverage", | ||
| #' "quantile_coverage_deviation" added. | ||
| #' @importFrom data.table setcolorder | ||
| #' @examples | ||
| #' library(magrittr) # pipe operator | ||
| #' example_quantile %>% | ||
| #' add_coverage() | ||
| #' @export | ||
| #' @keywords scoring | ||
| #' @export | ||
| add_coverage <- function(data) { | ||
| stored_attributes <- get_scoringutils_attributes(data) | ||
| data <- validate(data) | ||
| forecast_unit <- get_forecast_unit(data) | ||
| data_cols <- colnames(data) # store so we can reset column order later | ||
|
|
||
| # what happens if quantiles are not symmetric around the median? | ||
| # should things error? Also write tests for that. | ||
| interval_data <- quantile_to_interval(data, format = "wide") | ||
| interval_data[, interval_coverage := ifelse( | ||
| observed <= upper & observed >= lower, | ||
| TRUE, | ||
| FALSE) | ||
| ][, c("lower", "upper", "observed") := NULL] | ||
|
|
||
| data[, range := get_range_from_quantile(quantile)] | ||
|
|
||
| data <- merge(interval_data, data, by = unique(c(forecast_unit, "range"))) | ||
| data[, interval_coverage_deviation := interval_coverage - range / 100] | ||
| data[, quantile_coverage := observed <= predicted] | ||
| data[, quantile_coverage_deviation := quantile_coverage - quantile] | ||
|
|
||
| # reset column order | ||
| new_metrics <- c("interval_coverage", "interval_coverage_deviation", | ||
| "quantile_coverage", "quantile_coverage_deviation") | ||
| setcolorder(data, unique(c(data_cols, "range", new_metrics))) | ||
|
|
||
| # add coverage "metrics" to list of stored metrics | ||
| # this makes it possible to use `summarise_scores()` later on | ||
| stored_attributes[["metric_names"]] <- c( | ||
| stored_attributes[["metric_names"]], | ||
| new_metrics | ||
| ) | ||
| data <- assign_attributes(data, stored_attributes) | ||
| return(data[]) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so the reason we have to do all this stuff is we are only supporting one metric per function call vs allowing the output to be a data.frame and unnesting?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, we could have all functions return a data.frame and then merging things together in
score().Or a wrapper in
score()that checks whether the output is a data.frame, list or a vector? I'd be open to that, I just haven't thought about it long enough to have a good vision for how it would look like.I created an issue, $455. Could you please elaborate a bit on how you'd imagine this?