test-probabilist-bootstrapping.R 4.84 KiB
context("test bootstrapping for probabilistic evaluation")
library(testthat)
library(R.utils)
library(evalhyd)
all_metrics = c(
  # threshold-based
  'BS', 'BSS', 'BS_CRD', 'BS_LBD', 'REL_DIAG', 'CRPS_FROM_BS', 
  # CDF-based
  'CRPS_FROM_ECDF',
  # quantile-based
  'QS', 'CRPS_FROM_QS',
  # contingency table-based
  'POD', 'POFD', 'FAR', 'CSI', 'ROCSS',
  # ranks-based
# /!\ EXCLUDE BECAUSE OF RANDOM ELEMENT TO DEAL WITH TIES ----------------------
# 'RANK_HIST', 'DS', 'AS',
# ------------------------------------------------------------------------------
  # intervals
  'CR', 'AW', 'AWN', 'WS',
  # multivariate
  'ES'
# load some predicted and observed streamflow
dts_1yr = array(
  data=unlist(
    read.csv("./data/q_obs_1yr.csv", header=FALSE, nrows=1)
  ), 
  dim=c(366)
obs_1yr = array(
  data=unlist(
    read.csv("./data/q_obs_1yr.csv", header=TRUE, colClasses="numeric")
  ), 
  dim=c(1, 366)
prd_1yr = array(
  data=unlist(
    read.csv("./data/q_prd_1yr.csv", header=TRUE, colClasses="numeric")
  dim=c(50, 366)
thr = array(
  c(690, 534, 445), 
  dim=c(1, 3)
lvl = c(30., 80.)
# replicate year of data three times
obs_3yrs = cbind(obs_1yr, obs_1yr, obs_1yr)
prd_3yrs = cbind(prd_1yr, prd_1yr, prd_1yr)
# add dimensions for sites and lead times
dim(prd_1yr) = c(1,1,50,366)
dim(prd_3yrs) = c(1,1,50,366*3)
# ------------------------------------------------------------------------------
# compare bootstrap of three block years with three identical years
# ------------------------------------------------------------------------------
for (metric in all_metrics)
  testthat::test_that(
    metric,
      # bootstrap with only one year of data
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
x = evalhyd::evalp(obs_1yr, prd_1yr, metric, thr, "high", lvl, bootstrap=list(n_samples=10, len_sample=3, summary=0), dts=dts_1yr, seed=7)[[1]] # repeat year of data 3 times to correspond to bootstrap sample of length 3 y = evalhyd::evalp(obs_3yrs, prd_3yrs, metric, thr, "high", lvl)[[1]] testthat::expect_equal( # compare first sample only to have matching dimensions R.utils::extract(x, "4"=1), R.utils::extract(y, "4"=1), tolerance=1e-7 ) } ) } # ------------------------------------------------------------------------------ # compare bootstrap raw with mean+std summary # ------------------------------------------------------------------------------ for (metric in all_metrics) { # compute metrics raw = evalhyd::evalp(obs_1yr, prd_1yr, c(metric), thr, "high", lvl, bootstrap=list(n_samples=10, len_sample=3, summary=0), dts=dts_1yr)[[1]] # post-process raw outputs axes = 1:length(dim(raw)) axes = axes[-4] dims = dim(raw) dims[4] = 1 raw_mean = array( data=apply(raw, axes, mean), dim=dims ) raw_std = array( data=apply(raw, axes, sd), dim=dims ) # compute metric with mean+std summary mas = evalhyd::evalp(obs_1yr, prd_1yr, c(metric), thr, "high", lvl, bootstrap=list(n_samples=10, len_sample=3, summary=1), dts=dts_1yr)[[1]] # check mean testthat::test_that( paste(metric, "mean summary"), { testthat::expect_equal( raw_mean, R.utils::extract(mas, "4"=1), tolerance=1e-7 ) } ) # check standard deviation testthat::test_that( paste(metric, "standard deviation summary"), { testthat::expect_equal( raw_std, R.utils::extract(mas, "4"=2), tolerance=1e-7 ) }
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
) } # ------------------------------------------------------------------------------ # compare bootstrap raw with quantiles summary # ------------------------------------------------------------------------------ for (metric in all_metrics) { # compute metrics raw = evalhyd::evalp(obs_1yr, prd_1yr, c(metric), q_thr=thr, events="high", c_lvl=lvl, bootstrap=list(n_samples=10, len_sample=3, summary=0), dts=dts_1yr)[[1]] # post-process raw outputs q = c(0.05,0.10,0.25,0.50,0.75,0.90,0.95) axes = 1:length(dim(raw)) axes = axes[-4] dims = dim(raw) dims = dims[-4] dims = c(length(q), dims) raw_qtl = array( data=apply(raw, axes, quantile, q), dim=dims ) # compute metric with mean+std summary qtl = evalhyd::evalp(obs_1yr, prd_1yr, c(metric), thr, "high", lvl, bootstrap=list(n_samples=10, len_sample=3, summary=2), dts=dts_1yr)[[1]] # check each quantile value for (i in 1:7) { testthat::test_that( paste(metric, "quantile", q[i]), { testthat::expect_equal( R.utils::extract(raw_qtl, "1"=i, drop=TRUE), R.utils::extract(qtl, "4"=i, drop=TRUE), tolerance=1e-7 ) } ) } }