diff --git a/R/ACC.R b/R/ACC.R index 44c724c927675295ee54f26d7768380aaf96fc7a..ceb1e94e5257ef85de5b97ed97a19733c8e8d6ef 100644 --- a/R/ACC.R +++ b/R/ACC.R @@ -276,7 +276,7 @@ ACC <- function(exp, obs, dat_dim = 'dataset', lat_dim = 'lat', lon_dim = 'lon', } if (!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all the dimensions expect 'dat_dim' and 'memb_dim'.")) + "all the dimensions except 'dat_dim' and 'memb_dim'.")) } #----------------------------------------------------------------- diff --git a/R/Ano_CrossValid.R b/R/Ano_CrossValid.R index 99205020b7412afdf90513ad18dedf0b9302320d..d1996b9cd84023e8dc37e11af20b32b6e1cedd0f 100644 --- a/R/Ano_CrossValid.R +++ b/R/Ano_CrossValid.R @@ -18,7 +18,8 @@ #'@param dat_dim A character vector indicating the name of the dataset and #' member dimensions. When calculating the climatology, if data at one #' startdate (i.e., 'time_dim') is not complete along 'dat_dim', this startdate -#' along 'dat_dim' will be discarded. The default value is +#' along 'dat_dim' will be discarded. If there is no dataset dimension, it can be NULL. +#' The default value is #' "c('dataset', 'member')". #'@param memb_dim A character string indicating the name of the member #' dimension. Only used when parameter 'memb' is FALSE. It must be one element @@ -83,11 +84,25 @@ Ano_CrossValid <- function(exp, obs, time_dim = 'sdate', dat_dim = c('dataset', stop("Parameter 'time_dim' is not found in 'exp' or 'obs' dimension.") } ## dat_dim - if (!is.character(dat_dim)) { - stop("Parameter 'dat_dim' must be a character vector.") - } - if (!all(dat_dim %in% names(dim(exp))) | !all(dat_dim %in% names(dim(obs)))) { - stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.") + if (!is.null(dat_dim)) { + if (!is.character(dat_dim)) { + stop("Parameter 'dat_dim' must be a character vector.") + } + if (!all(dat_dim %in% names(dim(exp))) | !all(dat_dim %in% names(dim(obs)))) { + stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.", + " Set it as NULL if there is no dataset dimension.") + } + # If dat_dim is not in obs, add it in + if (any(!dat_dim %in% names(dim(obs)))) { + reset_obs_dim <- TRUE + ori_obs_dim <- dim(obs) + dim(obs) <- c(dim(obs), rep(1, length(dat_dim[which(!dat_dim %in% names(dim(obs)))]))) + names(dim(obs)) <- c(names(ori_obs_dim), dat_dim[which(!dat_dim %in% names(dim(obs)))]) + } else { + reset_obs_dim <- FALSE + } + } else { + reset_obs_dim <- FALSE } ## memb if (!is.logical(memb) | length(memb) > 1) { @@ -115,9 +130,11 @@ Ano_CrossValid <- function(exp, obs, time_dim = 'sdate', dat_dim = c('dataset', ## exp and obs (2) name_exp <- sort(names(dim(exp))) name_obs <- sort(names(dim(obs))) - for (i in 1:length(dat_dim)) { - name_exp <- name_exp[-which(name_exp == dat_dim[i])] - name_obs <- name_obs[-which(name_obs == dat_dim[i])] + if (!is.null(dat_dim)) { + for (i in 1:length(dat_dim)) { + name_exp <- name_exp[-which(name_exp == dat_dim[i])] + name_obs <- name_obs[-which(name_obs == dat_dim[i])] + } } if(!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have the same length of ", @@ -135,36 +152,65 @@ Ano_CrossValid <- function(exp, obs, time_dim = 'sdate', dat_dim = c('dataset', #----------------------------------- # Per-paired method: If any sdate along dat_dim is NA, turn all sdate points along dat_dim into NA. - pos <- rep(0, length(dat_dim)) # dat_dim: [dataset, member] - for (i in 1:length(dat_dim)) { - pos[i] <- which(names(dim(obs)) == dat_dim[i]) - } - outrows_exp <- MeanDims(exp, pos, na.rm = FALSE) + - MeanDims(obs, pos, na.rm = FALSE) - outrows_obs <- outrows_exp - - for (i in 1:length(pos)) { - outrows_exp <- InsertDim(outrows_exp, pos[i], dim(exp)[pos[i]]) - outrows_obs <- InsertDim(outrows_obs, pos[i], dim(obs)[pos[i]]) - } - exp_for_clim <- exp - obs_for_clim <- obs - exp_for_clim[which(is.na(outrows_exp))] <- NA - obs_for_clim[which(is.na(outrows_obs))] <- NA + if (!is.null(dat_dim)) { + pos <- rep(0, length(dat_dim)) # dat_dim: [dataset, member] + for (i in 1:length(dat_dim)) { + pos[i] <- which(names(dim(obs)) == dat_dim[i]) + } + outrows_exp <- MeanDims(exp, pos, na.rm = FALSE) + + MeanDims(obs, pos, na.rm = FALSE) + outrows_obs <- outrows_exp + + for (i in 1:length(pos)) { + outrows_exp <- InsertDim(outrows_exp, pos[i], dim(exp)[pos[i]]) + outrows_obs <- InsertDim(outrows_obs, pos[i], dim(obs)[pos[i]]) + } + exp_for_clim <- exp + obs_for_clim <- obs + exp_for_clim[which(is.na(outrows_exp))] <- NA + obs_for_clim[which(is.na(outrows_obs))] <- NA + } else { + exp_for_clim <- exp + obs_for_clim <- obs + } + #----------------------------------- + res <- Apply(list(exp, obs, exp_for_clim, obs_for_clim), + target_dims = c(time_dim, dat_dim), + fun = .Ano_CrossValid, dat_dim = dat_dim, + memb_dim = memb_dim, memb = memb, + ncores = ncores) - res <- Apply(list(exp, obs, exp_for_clim, obs_for_clim), - target_dims = c(time_dim, dat_dim), - fun = .Ano_CrossValid, - memb_dim = memb_dim, memb = memb, - ncores = ncores) + # Remove dat_dim in obs if obs doesn't have at first place + if (reset_obs_dim) { + res_obs_dim <- ori_obs_dim[-which(names(ori_obs_dim) == time_dim)] + if (!memb & memb_dim %in% names(res_obs_dim)) { + res_obs_dim <- res_obs_dim[-which(names(res_obs_dim) == memb_dim)] + } + if (is.integer(res_obs_dim) & length(res_obs_dim) == 0) { + res$obs <- as.vector(res$obs) + } else { + res$obs <- array(res$obs, dim = res_obs_dim) + } + } return(res) } -.Ano_CrossValid <- function(exp, obs, exp_for_clim, obs_for_clim, +.Ano_CrossValid <- function(exp, obs, exp_for_clim, obs_for_clim, dat_dim = c('dataset', 'member'), memb_dim = 'member', memb = TRUE, ncores = NULL) { + if (is.null(dat_dim)) { + ini_dims_exp <- dim(exp) + ini_dims_obs <- dim(obs) + ini_dims_exp_for_clim <- dim(exp) + ini_dims_obs_for_clim <- dim(exp) + exp <- InsertDim(exp, posdim = 2, lendim = 1, name = 'dataset') + exp_for_clim <- InsertDim(exp_for_clim, posdim = 2, lendim = 1, name = 'dataset') + obs <- InsertDim(obs, posdim = 2, lendim = 1, name = 'dataset') + obs_for_clim <- InsertDim(obs_for_clim, posdim = 2, lendim = 1, name = 'dataset') + } + # exp: [sdate, dat_dim, memb_dim] # obs: [sdate, dat_dim, memb_dim] ano_exp_list <- vector('list', length = dim(exp)[1]) #length: [sdate] @@ -222,5 +268,10 @@ Ano_CrossValid <- function(exp, obs, time_dim = 'sdate', dat_dim = c('dataset', ano_obs <- array(unlist(ano_obs_list), dim = c(dim(obs)[-1], dim(obs)[1])) ano_obs <- Reorder(ano_obs, c(length(dim(obs)), 1:(length(dim(obs)) - 1))) + if (is.null(dat_dim)) { + ano_exp <- array(ano_exp, dim = ini_dims_exp) + ano_obs <- array(ano_obs, dim = ini_dims_obs) + } + return(list(exp = ano_exp, obs = ano_obs)) } diff --git a/R/BrierScore.R b/R/BrierScore.R index c3673ad4273089059f13debc91d244554c2f90cd..22f497d18553240f67693d3891c912cc43be059a 100644 --- a/R/BrierScore.R +++ b/R/BrierScore.R @@ -57,13 +57,13 @@ #''bs_check_gres', 'bss_gres', 'rel_bias_corrected', 'gres_bias_corrected', #''unc_bias_corrected', and 'bss_bias_corrected' are (a) a number (b) an array #'with dimensions c(nexp, nobs, all the rest dimensions in 'exp' and 'obs' -#'expect 'time_dim' and 'memb_dim') (c) an array with dimensions of +#'except 'time_dim' and 'memb_dim') (c) an array with dimensions of #''exp' and 'obs' except 'time_dim' and 'memb_dim'\cr #'Items 'nk', 'fkbar', and 'okbar' are (a) a vector of length of bin number #'determined by 'threshold' (b) an array with dimensions c(nexp, nobs, -#'no. of bins, all the rest dimensions in 'exp' and 'obs' expect 'time_dim' and +#'no. of bins, all the rest dimensions in 'exp' and 'obs' except 'time_dim' and #''memb_dim') (c) an array with dimensions c(no. of bin, all the rest dimensions -#'in 'exp' and 'obs' expect 'time_dim' and 'memb_dim') +#'in 'exp' and 'obs' except 'time_dim' and 'memb_dim') #' #'@references #'Wilks (2006) Statistical Methods in the Atmospheric Sciences.\cr @@ -176,11 +176,11 @@ BrierScore <- function(exp, obs, thresholds = seq(0.1, 0.9, 0.1), time_dim = 'sd } if (any(!name_exp %in% name_obs) | any(!name_obs %in% name_exp)) { stop(paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'dat_dim' and 'memb_dim'.")) + "of all the dimensions except 'dat_dim' and 'memb_dim'.")) } if (!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'dat_dim' and 'memb_dim'.")) + "of all the dimensions except 'dat_dim' and 'memb_dim'.")) } ## ncores if (!is.null(ncores)) { diff --git a/R/Clim.R b/R/Clim.R index ce9ba2ed17b283d9a137df32e8b06275e7691f2e..c144025c1f8af795bb06afb31884949f868cb08f 100644 --- a/R/Clim.R +++ b/R/Clim.R @@ -173,7 +173,7 @@ Clim <- function(exp, obs, time_dim = 'sdate', dat_dim = c('dataset', 'member'), } if(!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have the same dimensions ", - "expect 'dat_dim'.")) + "except 'dat_dim'.")) } ############################### diff --git a/R/Consist_Trend.R b/R/Consist_Trend.R index b02aa5fe10cf64b6c574fb2314dd3ad91ab38029..ee956840bf613fc25b4d9ca65760a86e2f9bb4b3 100644 --- a/R/Consist_Trend.R +++ b/R/Consist_Trend.R @@ -124,7 +124,7 @@ Consist_Trend <- function(exp, obs, dat_dim = 'dataset', time_dim = 'sdate', int } if(!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all dimension expect 'dat_dim'.")) + "all dimension except 'dat_dim'.")) } ## interval if (!is.numeric(interval) | interval <= 0 | length(interval) > 1) { diff --git a/R/Corr.R b/R/Corr.R index 0382a393266a7b021a7aab39e69f9e7382e1155c..67efb09c0a1119c0970682de43518a32368f48a1 100644 --- a/R/Corr.R +++ b/R/Corr.R @@ -2,28 +2,29 @@ #' #'Calculate the correlation coefficient (Pearson, Kendall or Spearman) for #'an array of forecast and an array of observation. The correlations are -#'computed along time_dim, the startdate dimension. If comp_dim is given, -#'the correlations are computed only if obs along the comp_dim dimension are -#'complete between limits[1] and limits[2], i.e., there is no NA between -#'limits[1] and limits[2]. This option can be activated if the user wants to -#'account only for the forecasts which the corresponding observations are -#'available at all leadtimes.\cr +#'computed along 'time_dim' that usually refers to the start date dimension. If +#''comp_dim' is given, the correlations are computed only if obs along comp_dim +#'dimension are complete between limits[1] and limits[2], i.e., there is no NA +#'between limits[1] and limits[2]. This option can be activated if the user +#'wants to account only for the forecasts which the corresponding observations +#'are available at all leadtimes.\cr #'The confidence interval is computed by the Fisher transformation and the #'significance level relies on an one-sided student-T distribution.\cr -#'If the dataset has more than one member, ensemble mean is necessary necessary -#'before using this function since it only allows one dimension 'dat_dim' to -#'have inconsistent length between 'exp' and 'obs'. If all the dimensions of -#''exp' and 'obs' are identical, you can simply use apply() and cor() to +#'The function can calculate ensemble mean before correlation by 'memb_dim' +#'specified and 'memb = F'. If ensemble mean is not calculated, correlation will +#'be calculated for each member. +#'If there is only one dataset for exp and obs, you can simply use cor() to #'compute the correlation. #' -#'@param exp A named numeric array of experimental data, with at least two -#' dimensions 'time_dim' and 'dat_dim'. +#'@param exp A named numeric array of experimental data, with at least dimension +#' 'time_dim'. #'@param obs A named numeric array of observational data, same dimensions as #' parameter 'exp' except along 'dat_dim' and 'memb_dim'. #'@param time_dim A character string indicating the name of dimension along #' which the correlations are computed. The default value is 'sdate'. #'@param dat_dim A character string indicating the name of dataset (nobs/nexp) -#' dimension. The default value is 'dataset'. +#' dimension. The default value is 'dataset'. If there is no dataset +#' dimension, set NULL. #'@param comp_dim A character string indicating the name of dimension along which #' obs is taken into account only if it is complete. The default value #' is NULL. @@ -51,9 +52,10 @@ #' c(nexp, nobs, exp_memb, obs_memb, all other dimensions of exp except #' time_dim and memb_dim).\cr #'nexp is the number of experiment (i.e., 'dat_dim' in exp), and nobs is the -#'number of observation (i.e., 'dat_dim' in obs). exp_memb is the number of -#'member in experiment (i.e., 'memb_dim' in exp) and obs_memb is the number of -#'member in observation (i.e., 'memb_dim' in obs).\cr\cr +#'number of observation (i.e., 'dat_dim' in obs). If dat_dim is NULL, nexp and +#'nobs are omitted. exp_memb is the number of member in experiment (i.e., +#''memb_dim' in exp) and obs_memb is the number of member in observation (i.e., +#''memb_dim' in obs). If memb = F, exp_memb and obs_memb are omitted.\cr\cr #'\item{$corr}{ #' The correlation coefficient. #'} @@ -129,11 +131,14 @@ Corr <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', stop("Parameter 'time_dim' is not found in 'exp' or 'obs' dimension.") } ## dat_dim - if (!is.character(dat_dim) | length(dat_dim) > 1) { - stop("Parameter 'dat_dim' must be a character string.") - } - if (!dat_dim %in% names(dim(exp)) | !dat_dim %in% names(dim(obs))) { - stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.") + if (!is.null(dat_dim)) { + if (!is.character(dat_dim) | length(dat_dim) > 1) { + stop("Parameter 'dat_dim' must be a character string or NULL.") + } + if (!dat_dim %in% names(dim(exp)) | !dat_dim %in% names(dim(obs))) { + stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.", + " Set it as NULL if there is no dataset dimension.") + } } ## comp_dim if (!is.null(comp_dim)) { @@ -194,15 +199,17 @@ Corr <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', ## exp and obs (2) name_exp <- sort(names(dim(exp))) name_obs <- sort(names(dim(obs))) - name_exp <- name_exp[-which(name_exp == dat_dim)] - name_obs <- name_obs[-which(name_obs == dat_dim)] + if (!is.null(dat_dim)) { + name_exp <- name_exp[-which(name_exp == dat_dim)] + name_obs <- name_obs[-which(name_obs == dat_dim)] + } if (!is.null(memb_dim)) { name_exp <- name_exp[-which(name_exp == memb_dim)] name_obs <- name_obs[-which(name_obs == memb_dim)] } if(!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all dimension expect 'dat_dim' and 'memb_dim'.")) + "all dimension except 'dat_dim' and 'memb_dim'.")) } if (dim(exp)[time_dim] < 3) { stop("The length of time_dim must be at least 3 to compute correlation.") @@ -234,152 +241,121 @@ Corr <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', rm(obs_sub, outrows) } - if (is.null(memb_dim)) { - # Define output_dims - if (conf & pval) { - output_dims <- list(corr = c('nexp', 'nobs'), - p.val = c('nexp', 'nobs'), - conf.lower = c('nexp', 'nobs'), - conf.upper = c('nexp', 'nobs')) - } else if (conf & !pval) { - output_dims <- list(corr = c('nexp', 'nobs'), - conf.lower = c('nexp', 'nobs'), - conf.upper = c('nexp', 'nobs')) - } else if (!conf & pval) { - output_dims <- list(corr = c('nexp', 'nobs'), - p.val = c('nexp', 'nobs')) - } else { - output_dims <- list(corr = c('nexp', 'nobs')) - } - - res <- Apply(list(exp, obs), - target_dims = list(c(time_dim, dat_dim), - c(time_dim, dat_dim)), - output_dims = output_dims, - fun = .Corr, - time_dim = time_dim, method = method, - pval = pval, conf = conf, conf.lev = conf.lev, - ncores = ncores) - - } else { + if (!is.null(memb_dim)) { if (!memb) { #ensemble mean - name_exp <- names(dim(exp)) - margin_dims_ind <- c(1:length(name_exp))[-which(name_exp == memb_dim)] - exp <- apply(exp, margin_dims_ind, mean, na.rm = TRUE) #NOTE: remove NAs here - obs <- apply(obs, margin_dims_ind, mean, na.rm = TRUE) - - # Define output_dims - if (conf & pval) { - output_dims <- list(corr = c('nexp', 'nobs'), - p.val = c('nexp', 'nobs'), - conf.lower = c('nexp', 'nobs'), - conf.upper = c('nexp', 'nobs')) - } else if (conf & !pval) { - output_dims <- list(corr = c('nexp', 'nobs'), - conf.lower = c('nexp', 'nobs'), - conf.upper = c('nexp', 'nobs')) - } else if (!conf & pval) { - output_dims <- list(corr = c('nexp', 'nobs'), - p.val = c('nexp', 'nobs')) - } else { - output_dims <- list(corr = c('nexp', 'nobs')) - } - - res <- Apply(list(exp, obs), - target_dims = list(c(time_dim, dat_dim), - c(time_dim, dat_dim)), - output_dims = output_dims, - fun = .Corr, - time_dim = time_dim, method = method, - pval = pval, conf = conf, conf.lev = conf.lev, ncores_input = ncores, - ncores = ncores) - - } else { # correlation for each member - - # Define output_dims - if (conf & pval) { - output_dims <- list(corr = c('nexp', 'nobs', 'exp_memb', 'obs_memb'), - p.val = c('nexp', 'nobs', 'exp_memb', 'obs_memb'), - conf.lower = c('nexp', 'nobs', 'exp_memb', 'obs_memb'), - conf.upper = c('nexp', 'nobs', 'exp_memb', 'obs_memb')) - } else if (conf & !pval) { - output_dims <- list(corr = c('nexp', 'nobs', 'exp_memb', 'obs_memb'), - conf.lower = c('nexp', 'nobs', 'exp_memb', 'obs_memb'), - conf.upper = c('nexp', 'nobs', 'exp_memb', 'obs_memb')) - } else if (!conf & pval) { - output_dims <- list(corr = c('nexp', 'nobs', 'exp_memb', 'obs_memb'), - p.val = c('nexp', 'nobs', 'exp_memb', 'obs_memb')) - } else { - output_dims <- list(corr = c('nexp', 'nobs', 'exp_memb', 'obs_memb')) - } + exp <- MeanDims(exp, memb_dim, na.rm = TRUE) + obs <- MeanDims(obs, memb_dim, na.rm = TRUE) +# name_exp <- names(dim(exp)) +# margin_dims_ind <- c(1:length(name_exp))[-which(name_exp == memb_dim)] +# exp <- apply(exp, margin_dims_ind, mean, na.rm = TRUE) #NOTE: remove NAs here +# obs <- apply(obs, margin_dims_ind, mean, na.rm = TRUE) + memb_dim <- NULL + } + } - res <- Apply(list(exp, obs), + res <- Apply(list(exp, obs), target_dims = list(c(time_dim, dat_dim, memb_dim), c(time_dim, dat_dim, memb_dim)), - output_dims = output_dims, fun = .Corr, + dat_dim = dat_dim, memb_dim = memb_dim, time_dim = time_dim, method = method, pval = pval, conf = conf, conf.lev = conf.lev, ncores_input = ncores, - ncores = ncores) - } - } + ncores = ncores) return(res) } -.Corr <- function(exp, obs, time_dim = 'sdate', method = 'pearson', +.Corr <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', time_dim = 'sdate', method = 'pearson', conf = TRUE, pval = TRUE, conf.lev = 0.95, ncores_input = NULL) { - - if (length(dim(exp)) == 2) { - # exp: [sdate, dat_exp] - # obs: [sdate, dat_obs] - nexp <- as.numeric(dim(exp)[2]) - nobs <- as.numeric(dim(obs)[2]) - -# NOTE: Use sapply to replace the for loop - CORR <- sapply(1:nobs, function(i) { - sapply(1:nexp, function (x) { - if (any(!is.na(exp[, x])) && sum(!is.na(obs[, i])) > 2) { #NOTE: Is this necessary? - cor(exp[, x], obs[, i], - use = "pairwise.complete.obs", - method = method) - } else { - NA #CORR[, i] <- NA + if (is.null(memb_dim)) { + if (is.null(dat_dim)) { + # exp: [sdate] + # obs: [sdate] + nexp <- 1 + nobs <- 1 + CORR <- array(dim = c(nexp = nexp, nobs = nobs)) + if (any(!is.na(exp)) && sum(!is.na(obs)) > 2) { + CORR <- cor(exp, obs, use = "pairwise.complete.obs", method = method) } - }) - }) - if (is.null(dim(CORR))) { - CORR <- array(CORR, dim = c(1, 1)) - } - - } else { # member - - # exp: [sdate, dat_exp, memb_exp] - # obs: [sdate, dat_obs, memb_obs] - nexp <- as.numeric(dim(exp)[2]) - nobs <- as.numeric(dim(obs)[2]) - exp_memb <- as.numeric(dim(exp)[3]) - obs_memb <- as.numeric(dim(obs)[3]) + } else { + # exp: [sdate, dat_exp] + # obs: [sdate, dat_obs] + nexp <- as.numeric(dim(exp)[dat_dim]) + nobs <- as.numeric(dim(obs)[dat_dim]) + CORR <- array(dim = c(nexp = nexp, nobs = nobs)) + for (j in 1:nobs) { + for (y in 1:nexp) { + if (any(!is.na(exp[, y])) && sum(!is.na(obs[, j])) > 2) { + CORR[y, j] <- cor(exp[, y], obs[, j], + use = "pairwise.complete.obs", + method = method) + } + } + } +#---------------------------------------- +# Same as above calculation. +#TODO: Compare which is faster. +# CORR <- sapply(1:nobs, function(i) { +# sapply(1:nexp, function (x) { +# if (any(!is.na(exp[, x])) && sum(!is.na(obs[, i])) > 2) { +# cor(exp[, x], obs[, i], +# use = "pairwise.complete.obs", +# method = method) +# } else { +# NA +# } +# }) +# }) +#----------------------------------------- + } - CORR <- array(dim = c(nexp = nexp, nobs = nobs, exp_memb = exp_memb, obs_memb = obs_memb)) + } else { # memb_dim != NULL + exp_memb <- as.numeric(dim(exp)[memb_dim]) # memb_dim + obs_memb <- as.numeric(dim(obs)[memb_dim]) + + if (is.null(dat_dim)) { + # exp: [sdate, memb_exp] + # obs: [sdate, memb_obs] + nexp <- 1 + nobs <- 1 + CORR <- array(dim = c(nexp = nexp, nobs = nobs, exp_memb = exp_memb, obs_memb = obs_memb)) + + for (j in 1:obs_memb) { + for (y in 1:exp_memb) { + + if (any(!is.na(exp[,y])) && sum(!is.na(obs[, j])) > 2) { + CORR[, , y, j] <- cor(exp[, y], obs[, j], + use = "pairwise.complete.obs", + method = method) + } - for (j in 1:obs_memb) { - for (y in 1:exp_memb) { - CORR[, , y, j] <- sapply(1:nobs, function(i) { - sapply(1:nexp, function (x) { - if (any(!is.na(exp[, x, y])) && sum(!is.na(obs[, i, j])) > 2) { - cor(exp[, x, y], obs[, i, j], - use = "pairwise.complete.obs", - method = method) - } else { - NA #CORR[, i] <- NA } - }) - }) + } + } else { + # exp: [sdate, dat_exp, memb_exp] + # obs: [sdate, dat_obs, memb_obs] + nexp <- as.numeric(dim(exp)[dat_dim]) + nobs <- as.numeric(dim(obs)[dat_dim]) + + CORR <- array(dim = c(nexp = nexp, nobs = nobs, exp_memb = exp_memb, obs_memb = obs_memb)) + + for (j in 1:obs_memb) { + for (y in 1:exp_memb) { + CORR[, , y, j] <- sapply(1:nobs, function(i) { + sapply(1:nexp, function (x) { + if (any(!is.na(exp[, x, y])) && sum(!is.na(obs[, i, j])) > 2) { + cor(exp[, x, y], obs[, i, j], + use = "pairwise.complete.obs", + method = method) + } else { + NA + } + }) + }) + } + } } - } - } @@ -398,14 +374,21 @@ Corr <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', if (pval | conf) { if (method == "kendall" | method == "spearman") { - tmp <- apply(obs, c(1:length(dim(obs)))[-1], rank) # for memb_dim = NULL, 2; for memb_dim, c(2, 3) - names(dim(tmp))[1] <- time_dim - eno <- Eno(tmp, time_dim, ncores = ncores_input) + if (!is.null(dat_dim) | !is.null(memb_dim)) { + tmp <- apply(obs, c(1:length(dim(obs)))[-1], rank) # for memb_dim = NULL, 2; for memb_dim, c(2, 3) + names(dim(tmp))[1] <- time_dim + eno <- Eno(tmp, time_dim, ncores = ncores_input) + } else { + tmp <- rank(obs) + tmp <- array(tmp) + names(dim(tmp)) <- time_dim + eno <- Eno(tmp, time_dim, ncores = ncores_input) + } } else if (method == "pearson") { eno <- Eno(obs, time_dim, ncores = ncores_input) } - if (length(dim(exp)) == 2) { + if (is.null(memb_dim)) { eno_expand <- array(dim = c(nexp = nexp, nobs = nobs)) for (i in 1:nexp) { eno_expand[i, ] <- eno @@ -435,6 +418,21 @@ Corr <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', confhigh <- tanh(atanh(CORR) + qnorm(conf.upper) / sqrt(eno_expand - 3)) } +################################### + # Remove nexp and nobs if dat_dim = NULL + if (is.null(dat_dim) & !is.null(memb_dim)) { + dim(CORR) <- dim(CORR)[3:length(dim(CORR))] + if (pval) { + dim(p.val) <- dim(p.val)[3:length(dim(p.val))] + } + if (conf) { + dim(conflow) <- dim(conflow)[3:length(dim(conflow))] + dim(confhigh) <- dim(confhigh)[3:length(dim(confhigh))] + } + } + +################################### + if (pval & conf) { res <- list(corr = CORR, p.val = p.val, conf.lower = conflow, conf.upper = confhigh) @@ -447,6 +445,6 @@ Corr <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', res <- list(corr = CORR) } - return(res) + return(res) } diff --git a/R/NAO.R b/R/NAO.R index af4893ad0c5b904d0f62893f986282b4883d401d..6d48dba6aaec6eb8fc41dba2462c097e514ccc3f 100644 --- a/R/NAO.R +++ b/R/NAO.R @@ -194,7 +194,7 @@ NAO <- function(exp = NULL, obs = NULL, lat, lon, time_dim = 'sdate', } if (throw_error) { stop(paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'memb_dim'.")) + "of all the dimensions except 'memb_dim'.")) } } ## ftime_avg diff --git a/R/RMS.R b/R/RMS.R index b3c8ad4b016d18cc9f3dfd79ddaeb3bb38ba15b0..b3188fcd045518458cec57415c4bcd7da3b5621a 100644 --- a/R/RMS.R +++ b/R/RMS.R @@ -107,11 +107,14 @@ RMS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', stop("Parameter 'time_dim' is not found in 'exp' or 'obs' dimension.") } ## dat_dim - if (!is.character(dat_dim) | length(dat_dim) > 1) { - stop("Parameter 'dat_dim' must be a character string.") - } - if (!dat_dim %in% names(dim(exp)) | !dat_dim %in% names(dim(obs))) { - stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.") + if (!is.null(dat_dim)) { + if (!is.character(dat_dim) | length(dat_dim) > 1) { + stop("Parameter 'dat_dim' must be a character string or NULL.") + } + if (!dat_dim %in% names(dim(exp)) | !dat_dim %in% names(dim(obs))) { + stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.", + "Set it as NULL if there is no dataset dimension.") + } } ## comp_dim if (!is.null(comp_dim)) { @@ -151,11 +154,13 @@ RMS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', ## exp and obs (2) name_exp <- sort(names(dim(exp))) name_obs <- sort(names(dim(obs))) - name_exp <- name_exp[-which(name_exp == dat_dim)] - name_obs <- name_obs[-which(name_obs == dat_dim)] + if (!is.null(dat_dim)) { + name_exp <- name_exp[-which(name_exp == dat_dim)] + name_obs <- name_obs[-which(name_obs == dat_dim)] + } if(!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all dimension expect 'dat_dim'.")) + "all dimension except 'dat_dim'.")) } if (dim(exp)[time_dim] < 2) { stop("The length of time_dim must be at least 2 to compute RMS.") @@ -196,12 +201,22 @@ RMS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', } .RMS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', - conf = TRUE, conf.lev = 0.95, ncores_input = NULL) { - - # exp: [sdate, dat_exp] - # obs: [sdate, dat_obs] - nexp <- as.numeric(dim(exp)[2]) - nobs <- as.numeric(dim(obs)[2]) + conf = TRUE, conf.lev = 0.95, ncores_input = NULL) { + if (is.null(dat_dim)) { + # exp: [sdate] + # obs: [sdate] + nexp <- 1 + nobs <- 1 + ini_dims <- dim(exp) + dim(exp) <- c(ini_dims, dat_dim = 1) + dim(obs) <- c(ini_dims, dat_dim = 1) + } else { + # exp: [sdate, dat_exp] + # obs: [sdate, dat_obs] + nexp <- as.numeric(dim(exp)[2]) + nobs <- as.numeric(dim(obs)[2]) + } + nsdate <- as.numeric(dim(exp)[1]) dif <- array(dim = c(sdate = nsdate, nexp = nexp, nobs = nobs)) @@ -236,6 +251,16 @@ RMS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', conf.upper <- (eno * rms ** 2 / chi) ** 0.5 } + ################################### + # Remove nexp and nobs if dat_dim = NULL + if (is.null(dat_dim)) { + dim(rms) <- NULL + dim(conf.lower) <- NULL + dim(conf.upper) <- NULL + } + + ################################### + if (conf) { res <- list(rms = rms, conf.lower = conf.lower, conf.upper = conf.upper) } else { diff --git a/R/RMSSS.R b/R/RMSSS.R index 5fa96596ebacc4a2d46ed4f9e511adf504eb3e04..e44105cea96ba9f14c2e96f8488f4cc986c9826d 100644 --- a/R/RMSSS.R +++ b/R/RMSSS.R @@ -96,11 +96,14 @@ RMSSS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', stop("Parameter 'time_dim' is not found in 'exp' or 'obs' dimension.") } ## dat_dim - if (!is.character(dat_dim) | length(dat_dim) > 1) { - stop("Parameter 'dat_dim' must be a character string.") - } - if (!dat_dim %in% names(dim(exp)) | !dat_dim %in% names(dim(obs))) { - stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.") + if (!is.null(dat_dim)) { + if (!is.character(dat_dim) | length(dat_dim) > 1) { + stop("Parameter 'dat_dim' must be a character string or NULL.") + } + if (!dat_dim %in% names(dim(exp)) | !dat_dim %in% names(dim(obs))) { + stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.", + " Set it as NULL if there is no dataset dimension.") + } } ## pval if (!is.logical(pval) | length(pval) > 1) { @@ -116,11 +119,13 @@ RMSSS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', ## exp and obs (2) name_exp <- sort(names(dim(exp))) name_obs <- sort(names(dim(obs))) + if (!is.null(dat_dim)) { name_exp <- name_exp[-which(name_exp == dat_dim)] name_obs <- name_obs[-which(name_obs == dat_dim)] + } if(!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all dimension expect 'dat_dim'.")) + "all dimension except 'dat_dim'.")) } if (dim(exp)[time_dim] <= 2) { stop("The length of time_dim must be more than 2 to compute RMSSS.") @@ -151,10 +156,20 @@ RMSSS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', .RMSSS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', pval = TRUE, ncores_input = NULL) { + if (is.null(dat_dim)) { + # exp: [sdate] + # obs: [sdate] + nexp <- 1 + nobs <- 1 + dim(exp) <- c(dim(exp), nexp = nexp) + dim(obs) <- c(dim(obs), nobs = nobs) + } else { # exp: [sdate, dat_exp] # obs: [sdate, dat_obs] - nexp <- as.numeric(dim(exp)[2]) - nobs <- as.numeric(dim(obs)[2]) + nexp <- as.numeric(dim(exp)[2]) + nobs <- as.numeric(dim(obs)[2]) + } + nsdate <- as.numeric(dim(exp)[1]) p_val <- array(dim = c(nexp = nexp, nobs = nobs)) @@ -208,6 +223,14 @@ RMSSS <- function(exp, obs, time_dim = 'sdate', dat_dim = 'dataset', rmsss[which(!tmp)] <- NA } + ################################### + # Remove extra dimensions if dat_dim = NULL + if (is.null(dat_dim)) { + dim(rmsss) <- NULL + dim(p_val) <- NULL + } + ################################### + # output if (pval) { res <- list(rmsss = rmsss, p.val = p_val) diff --git a/R/RPS.R b/R/RPS.R index 8ded53e6d1546373f065bca04f07d12bebfbc73a..200c59c7b04a6c53012143b2317dd4f9d81bae7f 100644 --- a/R/RPS.R +++ b/R/RPS.R @@ -88,7 +88,7 @@ RPS <- function(exp, obs, time_dim = 'sdate', memb_dim = 'member', if (!identical(length(name_exp), length(name_obs)) | !identical(dim(exp)[name_exp], dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all dimensions expect 'memb_dim'.")) + "all dimensions except 'memb_dim'.")) } ## prob_thresholds if (!is.numeric(prob_thresholds) | !is.vector(prob_thresholds) | diff --git a/R/RPSS.R b/R/RPSS.R index 3b24777ddde51eaab88286ca6479a07724e7eeb3..cbd87bd2eea81ba203f6e40abd5139306752d8bf 100644 --- a/R/RPSS.R +++ b/R/RPSS.R @@ -108,7 +108,7 @@ RPSS <- function(exp, obs, ref = NULL, time_dim = 'sdate', memb_dim = 'member', if (!identical(length(name_exp), length(name_obs)) | !identical(dim(exp)[name_exp], dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all dimensions expect 'memb_dim'.")) + "all dimensions except 'memb_dim'.")) } if (!is.null(ref)) { name_ref <- sort(names(dim(ref))) @@ -116,7 +116,7 @@ RPSS <- function(exp, obs, ref = NULL, time_dim = 'sdate', memb_dim = 'member', if (!identical(length(name_exp), length(name_ref)) | !identical(dim(exp)[name_exp], dim(ref)[name_ref])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all dimensions expect 'memb_dim'.")) + "all dimensions except 'memb_dim'.")) } } ## prob_thresholds diff --git a/R/RatioRMS.R b/R/RatioRMS.R index f7e34b42f01fb2893a3d38112b49b69ce7c6d3b1..51f39846e1eb9c8e5a1616627de6c69ae848f8e6 100644 --- a/R/RatioRMS.R +++ b/R/RatioRMS.R @@ -21,7 +21,7 @@ #' computation. The default value is NULL. #' #'@return A list containing the numeric arrays with dimensions identical with -#' 'exp1', 'exp2', and 'obs', expect 'time_dim': +#' 'exp1', 'exp2', and 'obs', except 'time_dim': #'\item{$ratiorms}{ #' The ratio between the RMSE (i.e., RMSE1/RMSE2). #'} diff --git a/R/RatioSDRMS.R b/R/RatioSDRMS.R index 544ca6f8db3b6f85c73788fdecd5caa9c8557586..d527625c2daabfc5fc0fa2366ebec4a5292a46df 100644 --- a/R/RatioSDRMS.R +++ b/R/RatioSDRMS.R @@ -109,7 +109,7 @@ RatioSDRMS <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', name_obs <- name_obs[-which(name_obs == memb_dim)] if(!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have same length of ", - "all the dimensions expect 'dat_dim' and 'memb_dim'.")) + "all the dimensions except 'dat_dim' and 'memb_dim'.")) } ## pval if (!is.logical(pval) | length(pval) > 1) { diff --git a/R/ResidualCorr.R b/R/ResidualCorr.R index 7428d1b08be1ab462cbd37750e82835a2c91f797..8d9f0404fbfd1bd50d307da6950e7da4664859c1 100644 --- a/R/ResidualCorr.R +++ b/R/ResidualCorr.R @@ -125,7 +125,7 @@ ResidualCorr <- function(exp, obs, ref, N.eff = NA, time_dim = 'sdate', if (length(name_exp) != length(name_obs) | length(name_exp) != length(name_ref) | any(dim(exp)[name_exp] != dim(obs)[name_obs]) | any(dim(exp)[name_exp] != dim(ref)[name_ref])) { stop(paste0("Parameter 'exp', 'obs', and 'ref' must have same length of ", - "all dimensions expect 'memb_dim'.")) + "all dimensions except 'memb_dim'.")) } ## method if (!method %in% c("pearson", "kendall", "spearman")) { diff --git a/R/UltimateBrier.R b/R/UltimateBrier.R index aeaddcdcadcdd9d25e3a283d1ec8d24534f969d0..d2c4ac936016ef4f663f6005877b6a3220a06e88 100644 --- a/R/UltimateBrier.R +++ b/R/UltimateBrier.R @@ -5,14 +5,15 @@ #'to choose. #' #'@param exp A numeric array of forecast anomalies with named dimensions that -#' at least include 'dat_dim', 'memb_dim', and 'time_dim'. It can be provided +#' at least include 'memb_dim', and 'time_dim'. It can be provided #' by \code{Ano()}. #'@param obs A numeric array of observational reference anomalies with named -#' dimensions that at least include 'dat_dim' and 'time_dim'. If it has +#' dimensions that at least include 'time_dim'. If it has #' 'memb_dim', the length must be 1. The dimensions should be consistent with #' 'exp' except 'dat_dim' and 'memb_dim'. It can be provided by \code{Ano()}. #'@param dat_dim A character string indicating the name of the dataset -#' dimension in 'exp' and 'obs'. The default value is 'dataset'. +#' dimension in 'exp' and 'obs'. The default value is 'dataset'. If there is no dataset +#' dimension, set NULL. #'@param memb_dim A character string indicating the name of the member #' dimension in 'exp' (and 'obs') for ensemble mean calculation. The default #' value is 'member'. @@ -55,7 +56,7 @@ #'same dimensions: #'c(nexp, nobs, no. of bins, the rest dimensions of 'exp' except 'time_dim' and #''memb_dim'). 'nexp' and 'nobs' is the length of dataset dimension in 'exp' -#'and 'obs' respectively.\cr +#'and 'obs' respectively. If dat_dim is NULL, nexp and nobs are omitted.\cr #'The list of 4 includes: #' \itemize{ #' \item{$bs: Brier Score} @@ -102,12 +103,15 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti stop("Parameter 'exp' and 'obs' must have dimension names.") } ## dat_dim - if (!is.character(dat_dim) | length(dat_dim) > 1) { - stop("Parameter 'dat_dim' must be a character string.") - } - if (!dat_dim %in% names(dim(exp)) | !dat_dim %in% names(dim(obs))) { - stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.") + if (!is.null(dat_dim)) { + if (!is.character(dat_dim) | length(dat_dim) > 1) { + stop("Parameter 'dat_dim' must be a character string or NULL.") + } + if (!dat_dim %in% names(dim(exp)) | !dat_dim %in% names(dim(obs))) { + stop("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.") + } } + ## memb_dim if (!is.character(memb_dim) | length(memb_dim) > 1) { stop("Parameter 'memb_dim' must be a character string.") @@ -137,11 +141,11 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti name_obs <- name_obs[-which(name_obs == dat_dim)] if (any(name_exp != name_obs)) { stop(paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'dat_dim' and 'memb_dim'.")) + "of all the dimensions except 'dat_dim' and 'memb_dim'.")) } if (!all(dim(exp)[name_exp] == dim(obs)[name_obs])) { stop(paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'dat_dim' and 'memb_dim'.")) + "of all the dimensions except 'dat_dim' and 'memb_dim'.")) } ## quantile if (!is.logical(quantile) | length(quantile) > 1) { @@ -183,6 +187,7 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti target_dims = list(c(time_dim, dat_dim, memb_dim), c(time_dim, dat_dim, memb_dim)), fun = .UltimateBrier, + dat_dim = dat_dim, memb_dim = memb_dim, thr = thr, type = type, decomposition = decomposition, ncores = ncores)$output1 @@ -203,6 +208,7 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti target_dims = list(c(time_dim, dat_dim), c(time_dim, dat_dim)), fun = .UltimateBrier, + dat_dim = dat_dim, memb_dim = memb_dim, thr = thr, type = type, decomposition = decomposition, ncores = ncores) @@ -217,8 +223,8 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti return(res) } -.UltimateBrier <- function(exp, obs, thr = c(5/100, 95/100), type = 'BS', - decomposition = TRUE) { +.UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', thr = c(5/100, 95/100), + type = 'BS', decomposition = TRUE) { # If exp and obs are probablistics # exp: [sdate, nexp] # obs: [sdate, nobs] @@ -229,6 +235,10 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti #NOTE: 'thr' is used in 'FairEnsembleBSS' and 'FairEnsembleBS'. But if quantile = F and # thr is real value, does it work? if (type == 'FairEnsembleBSS') { + if (is.null(dat_dim)) { + obs <- InsertDim(obs, posdim = 2, lendim = 1, name = 'dataset') + exp <- InsertDim(exp, posdim = 2, lendim = 1, name = 'dataset') + } size_ens_ref <- prod(dim(obs)[c(1, 3)]) res <- array(dim = c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2]), @@ -245,6 +255,9 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti } } } + if (is.null(dat_dim)) { + dim(res) <- dim(res)[3:length(dim(res))] + } } else if (type == 'FairEnsembleBS') { #NOTE: The calculation in s2dverification::UltimateBrier is wrong. In the final stage, @@ -252,6 +265,10 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti # but the 3rd dim of result is 'bins' instead of decomposition. 'FairEnsembleBS' does # not have decomposition. # The calculation is fixed here. + if (is.null(dat_dim)) { + obs <- InsertDim(obs, posdim = 2, lendim = 1, name = 'dataset') + exp <- InsertDim(exp, posdim = 2, lendim = 1, name = 'dataset') + } res <- array(dim = c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2]), bin = length(thr) + 1)) @@ -264,10 +281,17 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti } } } + if (is.null(dat_dim)) { + dim(res) <- dim(res)[3:length(dim(res))] + } # tmp <- res[, , 1] - res[, , 2] + res[, , 3] # res <- array(tmp, dim = c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2]))) } else if (type == 'BS') { + if (is.null(dat_dim)) { + obs <- InsertDim(obs, posdim = 2, lendim = 1, name = 'dataset') + exp <- InsertDim(exp, posdim = 2, lendim = 1, name = 'dataset') + } comp <- array(dim = c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2]), comp = 3)) @@ -280,17 +304,28 @@ UltimateBrier <- function(exp, obs, dat_dim = 'dataset', memb_dim = 'member', ti } if (decomposition) { rel <- comp[, , 1] - dim(rel) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) res <- comp[, , 2] - dim(res) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) unc <- comp[, , 3] - dim(unc) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) bs <- rel - res + unc - dim(bs) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) + if (is.null(dat_dim)) { + dim(rel) <- NULL + dim(res) <- NULL + dim(unc) <- NULL + dim(bs) <- NULL + } else { + dim(rel) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) + dim(res) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) + dim(unc) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) + dim(bs) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) + } res <- list(bs = bs, rel = rel, res = res, unc = unc) } else { bs <- comp[, , 1] - comp[, , 2] + comp[, , 3] - dim(bs) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) + if (is.null(dat_dim)) { + dim(bs) <- NULL + } else { + dim(bs) <- c(nexp = as.numeric(dim(exp)[2]), nobs = as.numeric(dim(obs)[2])) + } res <- list(bs = bs) } diff --git a/man/Ano_CrossValid.Rd b/man/Ano_CrossValid.Rd index d2234a1623901efa767aba83bbd4c5eb532940a7..2a82713159b5d3357904e190a88486aadea52d1b 100644 --- a/man/Ano_CrossValid.Rd +++ b/man/Ano_CrossValid.Rd @@ -25,10 +25,11 @@ parameter 'exp' except along 'dat_dim'.} The default value is 'sdate'.} \item{dat_dim}{A character vector indicating the name of the dataset and -member dimensions. When calculating the climatology, if data at one -startdate (i.e., 'time_dim') is not complete along 'dat_dim', this startdate -along 'dat_dim' will be discarded. The default value is -"c('dataset', 'member')".} + member dimensions. When calculating the climatology, if data at one + startdate (i.e., 'time_dim') is not complete along 'dat_dim', this startdate + along 'dat_dim' will be discarded. If there is no dataset dimension, it can be NULL. +The default value is + "c('dataset', 'member')".} \item{memb_dim}{A character string indicating the name of the member dimension. Only used when parameter 'memb' is FALSE. It must be one element diff --git a/man/BrierScore.Rd b/man/BrierScore.Rd index 9271a2adb8fca99ed95483a36b46545e219cd47c..76fb27eb0106b2a38a4222af784b268abcaa45a2 100644 --- a/man/BrierScore.Rd +++ b/man/BrierScore.Rd @@ -73,13 +73,13 @@ Items 'rel', 'res', 'unc', 'bs', 'bs_check_res', 'bss_res', 'gres', 'bs_check_gres', 'bss_gres', 'rel_bias_corrected', 'gres_bias_corrected', 'unc_bias_corrected', and 'bss_bias_corrected' are (a) a number (b) an array with dimensions c(nexp, nobs, all the rest dimensions in 'exp' and 'obs' -expect 'time_dim' and 'memb_dim') (c) an array with dimensions of +except 'time_dim' and 'memb_dim') (c) an array with dimensions of 'exp' and 'obs' except 'time_dim' and 'memb_dim'\cr Items 'nk', 'fkbar', and 'okbar' are (a) a vector of length of bin number determined by 'threshold' (b) an array with dimensions c(nexp, nobs, -no. of bins, all the rest dimensions in 'exp' and 'obs' expect 'time_dim' and +no. of bins, all the rest dimensions in 'exp' and 'obs' except 'time_dim' and 'memb_dim') (c) an array with dimensions c(no. of bin, all the rest dimensions -in 'exp' and 'obs' expect 'time_dim' and 'memb_dim') +in 'exp' and 'obs' except 'time_dim' and 'memb_dim') } \description{ Compute the Brier score (BS) and the components of its standard decompostion diff --git a/man/Corr.Rd b/man/Corr.Rd index 077791fbeeb5e100a18e5b44c26a0b4753772d39..4cbd0986bf3b6dbbca2fc67715ac2f56c18c96a9 100644 --- a/man/Corr.Rd +++ b/man/Corr.Rd @@ -21,8 +21,8 @@ Corr( ) } \arguments{ -\item{exp}{A named numeric array of experimental data, with at least two -dimensions 'time_dim' and 'dat_dim'.} +\item{exp}{A named numeric array of experimental data, with at least dimension +'time_dim'.} \item{obs}{A named numeric array of observational data, same dimensions as parameter 'exp' except along 'dat_dim' and 'memb_dim'.} @@ -31,7 +31,8 @@ parameter 'exp' except along 'dat_dim' and 'memb_dim'.} which the correlations are computed. The default value is 'sdate'.} \item{dat_dim}{A character string indicating the name of dataset (nobs/nexp) -dimension. The default value is 'dataset'.} +dimension. The default value is 'dataset'. If there is no dataset +dimension, set NULL.} \item{comp_dim}{A character string indicating the name of dimension along which obs is taken into account only if it is complete. The default value @@ -68,9 +69,10 @@ A list containing the numeric arrays with dimension:\cr c(nexp, nobs, exp_memb, obs_memb, all other dimensions of exp except time_dim and memb_dim).\cr nexp is the number of experiment (i.e., 'dat_dim' in exp), and nobs is the -number of observation (i.e., 'dat_dim' in obs). exp_memb is the number of -member in experiment (i.e., 'memb_dim' in exp) and obs_memb is the number of -member in observation (i.e., 'memb_dim' in obs).\cr\cr +number of observation (i.e., 'dat_dim' in obs). If dat_dim is NULL, nexp and +nobs are omitted. exp_memb is the number of member in experiment (i.e., +'memb_dim' in exp) and obs_memb is the number of member in observation (i.e., +'memb_dim' in obs). If memb = F, exp_memb and obs_memb are omitted.\cr\cr \item{$corr}{ The correlation coefficient. } @@ -87,18 +89,18 @@ member in observation (i.e., 'memb_dim' in obs).\cr\cr \description{ Calculate the correlation coefficient (Pearson, Kendall or Spearman) for an array of forecast and an array of observation. The correlations are -computed along time_dim, the startdate dimension. If comp_dim is given, -the correlations are computed only if obs along the comp_dim dimension are -complete between limits[1] and limits[2], i.e., there is no NA between -limits[1] and limits[2]. This option can be activated if the user wants to -account only for the forecasts which the corresponding observations are -available at all leadtimes.\cr +computed along 'time_dim' that usually refers to the start date dimension. If +'comp_dim' is given, the correlations are computed only if obs along comp_dim +dimension are complete between limits[1] and limits[2], i.e., there is no NA +between limits[1] and limits[2]. This option can be activated if the user +wants to account only for the forecasts which the corresponding observations +are available at all leadtimes.\cr The confidence interval is computed by the Fisher transformation and the significance level relies on an one-sided student-T distribution.\cr -If the dataset has more than one member, ensemble mean is necessary necessary -before using this function since it only allows one dimension 'dat_dim' to -have inconsistent length between 'exp' and 'obs'. If all the dimensions of -'exp' and 'obs' are identical, you can simply use apply() and cor() to +The function can calculate ensemble mean before correlation by 'memb_dim' +specified and 'memb = F'. If ensemble mean is not calculated, correlation will +be calculated for each member. +If there is only one dataset for exp and obs, you can simply use cor() to compute the correlation. } \examples{ diff --git a/man/RatioRMS.Rd b/man/RatioRMS.Rd index 194c6b9899e84dfd1772117cc9eade22d2e1e7b7..3330eb5a31aec9507a6836451f38ef829fcc108d 100644 --- a/man/RatioRMS.Rd +++ b/man/RatioRMS.Rd @@ -30,7 +30,7 @@ computation. The default value is NULL.} } \value{ A list containing the numeric arrays with dimensions identical with - 'exp1', 'exp2', and 'obs', expect 'time_dim': + 'exp1', 'exp2', and 'obs', except 'time_dim': \item{$ratiorms}{ The ratio between the RMSE (i.e., RMSE1/RMSE2). } diff --git a/man/UltimateBrier.Rd b/man/UltimateBrier.Rd index 2cad133c23d620eeee9e0a57d7466550da9478cf..0dfa772e00dd9d9efa0679b781fee56a76ae855f 100644 --- a/man/UltimateBrier.Rd +++ b/man/UltimateBrier.Rd @@ -19,16 +19,17 @@ UltimateBrier( } \arguments{ \item{exp}{A numeric array of forecast anomalies with named dimensions that -at least include 'dat_dim', 'memb_dim', and 'time_dim'. It can be provided +at least include 'memb_dim', and 'time_dim'. It can be provided by \code{Ano()}.} \item{obs}{A numeric array of observational reference anomalies with named -dimensions that at least include 'dat_dim' and 'time_dim'. If it has +dimensions that at least include 'time_dim'. If it has 'memb_dim', the length must be 1. The dimensions should be consistent with 'exp' except 'dat_dim' and 'memb_dim'. It can be provided by \code{Ano()}.} \item{dat_dim}{A character string indicating the name of the dataset -dimension in 'exp' and 'obs'. The default value is 'dataset'.} +dimension in 'exp' and 'obs'. The default value is 'dataset'. If there is no dataset +dimension, set NULL.} \item{memb_dim}{A character string indicating the name of the member dimension in 'exp' (and 'obs') for ensemble mean calculation. The default @@ -78,7 +79,7 @@ is an array of Brier scores or Brier skill scores. All the arrays have the same dimensions: c(nexp, nobs, no. of bins, the rest dimensions of 'exp' except 'time_dim' and 'memb_dim'). 'nexp' and 'nobs' is the length of dataset dimension in 'exp' -and 'obs' respectively.\cr +and 'obs' respectively. If dat_dim is NULL, nexp and nobs are omitted.\cr The list of 4 includes: \itemize{ \item{$bs: Brier Score} diff --git a/tests/testthat/test-ACC.R b/tests/testthat/test-ACC.R index 5c3672552930be48e114949fdb2301a8ab429bce..04e60ad0888ee97ed49aa2d310fa814d9d87cd4c 100644 --- a/tests/testthat/test-ACC.R +++ b/tests/testthat/test-ACC.R @@ -152,7 +152,7 @@ test_that("1. Input checks", { obs = array(1:4, dim = c(dataset = 2, member = 2, lat = 1, lon = 1)), lat = c(1, 2), lon = c(1), avg_dim = NULL), - "Parameter 'exp' and 'obs' must have same length of all the dimensions expect 'dat_dim' and 'memb_dim'." + "Parameter 'exp' and 'obs' must have same length of all the dimensions except 'dat_dim' and 'memb_dim'." ) }) diff --git a/tests/testthat/test-Ano_CrossValid.R b/tests/testthat/test-Ano_CrossValid.R index b66fc5fbf54113b71826e7adf79d014890c003e0..2d7c00c127b75ad9e240630bce109fd9b001d904 100644 --- a/tests/testthat/test-Ano_CrossValid.R +++ b/tests/testthat/test-Ano_CrossValid.R @@ -13,6 +13,12 @@ exp2 <- array(rnorm(30), dim = c(member = 3, ftime = 2, sdate = 5)) set.seed(2) obs2 <- array(rnorm(20), dim = c(ftime = 2, member = 2, sdate = 5)) +# dat3 +set.seed(1) +exp3 <- array(rnorm(30), dim = c(ftime = 2, sdate = 5)) +set.seed(2) +obs3 <- array(rnorm(20), dim = c(ftime = 2, sdate = 5)) + ############################################## test_that("1. Input checks", { @@ -51,7 +57,7 @@ test_that("1. Input checks", { ) expect_error( Ano_CrossValid(exp1, obs1, dat_dim = 'dat'), - "Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension." + "Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension. Set it as NULL if there is no dataset dimension." ) # memb expect_error( @@ -136,6 +142,28 @@ test_that("3. dat2", { }) +############################################## +test_that("4. dat3", { + expect_equal( + names(Ano_CrossValid(exp3, obs3, dat_dim = NULL)), + c("exp", "obs") + ) + expect_equal( + dim(Ano_CrossValid(exp3, obs3, dat_dim = NULL)$exp), + c(sdate = 5, ftime = 2) + ) + expect_equal( + Ano_CrossValid(exp3, obs3, dat_dim = NULL)$exp[, 2], + c(-0.1182939, 1.6462530, -1.3734335, 0.5750579, -0.7295835), + tolerance = 0.0001 + ) + expect_equal( + Ano_CrossValid(exp3, obs3, dat_dim = NULL)$exp[, 2], + c(-0.1182939, 1.6462530, -1.3734335, 0.5750579, -0.7295835), + tolerance = 0.0001 + ) + +}) diff --git a/tests/testthat/test-BrierScore.R b/tests/testthat/test-BrierScore.R index 5668a089972352b29db2d553acb7134a3ede2203..e2c34f95744114b72ff7f5ac89131bf29f5da250 100644 --- a/tests/testthat/test-BrierScore.R +++ b/tests/testthat/test-BrierScore.R @@ -51,7 +51,7 @@ test_that("1. Input checks", { expect_error( BrierScore(exp3, obs3), paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'dat_dim' and 'memb_dim'.") + "of all the dimensions except 'dat_dim' and 'memb_dim'.") ) # thresholds expect_error( diff --git a/tests/testthat/test-Clim.R b/tests/testthat/test-Clim.R index 7751afb405c23c4e42cc5587eefa7f670182d14e..f5e288ec2c4b956a44c2494d8ae86f280288a2a1 100644 --- a/tests/testthat/test-Clim.R +++ b/tests/testthat/test-Clim.R @@ -134,7 +134,7 @@ test_that("1. Input checks", { expect_error( Clim(array(1:10, dim = c(dataset = 2, member = 5, sdate = 4, ftime = 3)), array(1:4, dim = c(dataset = 2, member = 2, sdate = 5, ftime = 3))), - "Parameter 'exp' and 'obs' must have the same dimensions expect 'dat_dim'." + "Parameter 'exp' and 'obs' must have the same dimensions except 'dat_dim'." ) }) diff --git a/tests/testthat/test-Consist_Trend.R b/tests/testthat/test-Consist_Trend.R index aa66f45761c6aa6b8bca1f02d7fbf8649882b038..91dacf7085035a0b16a6ab9689309a517c5ad5a6 100644 --- a/tests/testthat/test-Consist_Trend.R +++ b/tests/testthat/test-Consist_Trend.R @@ -62,7 +62,7 @@ test_that("1. Input checks", { Consist_Trend(array(1:10, dim = c(dataset = 2, member = 5, sdate = 4, ftime = 3)), array(1:4, dim = c(dataset = 2, member = 2, sdate = 5, ftime = 3))), paste0("Parameter 'exp' and 'obs' must have same length of ", - "all dimension expect 'dat_dim'.") + "all dimension except 'dat_dim'.") ) # interval expect_error( diff --git a/tests/testthat/test-Corr.R b/tests/testthat/test-Corr.R index 9d5d4a3653ca55366919e8cf0bb87676972bf4b9..6e3c0162bb3c50cce3e28d0454c2da1672411ba2 100644 --- a/tests/testthat/test-Corr.R +++ b/tests/testthat/test-Corr.R @@ -40,6 +40,29 @@ context("s2dv::Corr tests") obs4 <- array(rnorm(10), dim = c(member = 1, dataset = 1, sdate = 5, lat = 2)) + # dat5: exp and obs have memb_dim and dataset = NULL + set.seed(1) + exp5 <- array(rnorm(90), dim = c(member = 3, sdate = 5, + lat = 2, lon = 3)) + + set.seed(2) + obs5 <- array(rnorm(30), dim = c(member = 1, sdate = 5, + lat = 2, lon = 3)) + + # dat6: exp and obs have memb_dim = NULL and dataset = NULL + set.seed(1) + exp6 <- array(rnorm(90), dim = c(sdate = 5, lat = 2, lon = 3)) + + set.seed(2) + obs6 <- array(rnorm(30), dim = c(sdate = 5, lat = 2, lon = 3)) + + # dat7: exp and obs have memb_dim = NULL and dataset = 1 + set.seed(1) + exp7 <- array(rnorm(90), dim = c(dataset = 1, sdate = 5, lat = 2, lon = 3)) + + set.seed(2) + obs7 <- array(rnorm(30), dim = c(dataset = 1, sdate = 5, lat = 2, lon = 3)) + ############################################## test_that("1. Input checks", { @@ -132,7 +155,7 @@ test_that("1. Input checks", { expect_error( Corr(exp = array(1:10, dim = c(sdate = 1, dataset = 5, a = 1)), obs = array(1:4, dim = c(a = 1, sdate = 2, dataset = 2))), - "Parameter 'exp' and 'obs' must have same length of all dimension expect 'dat_dim'." + "Parameter 'exp' and 'obs' must have same length of all dimension except 'dat_dim' and 'memb_dim'." ) expect_error( Corr(exp = array(1:10, dim = c(sdate = 2, dataset = 5, a = 1)), @@ -392,4 +415,70 @@ test_that("5. Output checks: dat4", { ) }) + +############################################## +test_that("6. Output checks: dat5", { + expect_equal( + dim(Corr(exp5, obs5, dat_dim = NULL, memb_dim = 'member')$corr), + c(exp_memb = 3, obs_memb = 1, lat = 2, lon = 3) + ) + expect_equal( + names(Corr(exp5, obs5, dat_dim = NULL, memb_dim = 'member')), + c("corr", "p.val", "conf.lower", "conf.upper") + ) + expect_equal( + names(Corr(exp5, obs5, dat_dim = NULL, memb_dim = 'member', pval = FALSE, conf = FALSE)), + c("corr") + ) + expect_equal( + mean(Corr(exp5, obs5, dat_dim = NULL, memb_dim = 'member', pval = FALSE, conf = FALSE)$corr), + 0.1880204, + tolerance = 0.0001 + ) +}) +############################################## +test_that("7. Output checks: dat6", { + expect_equal( + dim(Corr(exp6, obs6, dat_dim = NULL, memb_dim = NULL)$corr), + c(lat = 2, lon = 3) + ) + expect_equal( + names(Corr(exp6, obs6, dat_dim = NULL, memb_dim = NULL)), + c("corr", "p.val", "conf.lower", "conf.upper") + ) + expect_equal( + names(Corr(exp6, obs6, dat_dim = NULL, memb_dim = NULL, pval = FALSE, conf = FALSE)), + c("corr") + ) + expect_equal( + mean(Corr(exp6, obs6, dat_dim = NULL, memb_dim = NULL, pval = FALSE, conf = FALSE)$corr), + 0.1084488, + tolerance = 0.0001 + ) + # kendall + expect_equal( + as.vector(Corr(exp6, obs6, dat_dim = NULL, memb_dim = NULL, method = 'kendall')$corr[2:4]), + c(0.0, 0.6, 0.2), + tolerance = 0.0001 + ) + expect_equal( + as.vector(Corr(exp6, obs6, dat_dim = NULL, memb_dim = NULL, method = 'kendall')$p[2:4]), + c(0.5000000, 0.1423785, 0.3735300), + tolerance = 0.0001 + ) + expect_equal( + as.vector(Corr(exp6, obs6, dat_dim = NULL, memb_dim = NULL, method = 'kendall')$conf.low[2:4]), + c(-0.8822664, -0.5997500, -0.8284490), + tolerance = 0.0001 + ) + +}) +############################################## +test_that("8. Output checks: dat6 and dat7", { + expect_equal( + mean(Corr(exp6, obs6, dat_dim = NULL, memb_dim = NULL, pval = FALSE, conf = FALSE)$corr), + mean(Corr(exp7, obs7, memb_dim = NULL, pval = FALSE, conf = FALSE)$corr), + tolerance = 0.0001 + ) +}) ############################################## diff --git a/tests/testthat/test-NAO.R b/tests/testthat/test-NAO.R index f3c6d21f5574be54e0b05513d887e927aa6f7a87..2da0d407ea986175a9a3d2c73605bd5aead29451 100644 --- a/tests/testthat/test-NAO.R +++ b/tests/testthat/test-NAO.R @@ -95,12 +95,12 @@ test_that("1. Input checks", { expect_error( NAO(exp1, array(rnorm(10), dim = c(member = 1, sdate = 3, ftime = 4, lat = 2, lon = 2))), paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'memb_dim'.") + "of all the dimensions except 'memb_dim'.") ) expect_error( NAO(exp1, array(rnorm(10), dim = c(dataset = 1, member = 1, sdate = 3, ftime = 4, lat = 1, lon = 2))), paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'memb_dim'.") + "of all the dimensions except 'memb_dim'.") ) # ftime_avg expect_error( diff --git a/tests/testthat/test-RMS.R b/tests/testthat/test-RMS.R index 6e18bee447b4397a471350b89a12cf3c1b663f67..f69cfd8a1de8e4db627dcfb5e9d0e0ca2a845080 100644 --- a/tests/testthat/test-RMS.R +++ b/tests/testthat/test-RMS.R @@ -17,6 +17,13 @@ context("s2dv::RMS tests") set.seed(6) obs2 <- rnorm(10) + # dat3 + set.seed(1) + exp3 <- array(rnorm(120), dim = c(sdate = 5, ftime = 2, lon = 1, lat = 4)) + + set.seed(2) + obs3 <- array(rnorm(80), dim = c(sdate = 5, ftime = 2, lon = 1, lat = 4)) + ############################################## test_that("1. Input checks", { @@ -89,7 +96,7 @@ test_that("1. Input checks", { expect_error( RMS(exp = array(1:10, dim = c(sdate = 1, dataset = 5, a = 1)), obs = array(1:4, dim = c(a = 1, sdate = 2, dataset = 2))), - "Parameter 'exp' and 'obs' must have same length of all dimension expect 'dat_dim'." + "Parameter 'exp' and 'obs' must have same length of all dimension except 'dat_dim'." ) expect_error( RMS(exp = array(1:5, dim = c(sdate = 1, dataset = 5, a = 1)), @@ -186,3 +193,18 @@ test_that("3. Output checks: dat2", { }) ############################################## +test_that("4. Output checks: dat3", { + + expect_equal( + dim(RMS(exp3, obs3, dat_dim = NULL)$rms), + c(ftime = 2, lon = 1, lat = 4) + ) + + expect_equal( + as.vector(RMS(exp3, obs3, dat_dim = NULL)$rms), + c(1.6458118, 0.8860392, 0.8261295, 1.1681939, 2.1693538, 1.3064454, 0.5384229, 1.1215333), + tolerance = 0.00001 + ) +}) + +############################################## \ No newline at end of file diff --git a/tests/testthat/test-RMSSS.R b/tests/testthat/test-RMSSS.R index 7d2a16da9da52c492dad263985f71c042783927b..d592130fc7c8f1ea6478da94a4e5d8677586fdb0 100644 --- a/tests/testthat/test-RMSSS.R +++ b/tests/testthat/test-RMSSS.R @@ -25,6 +25,12 @@ context("s2dv::RMSSS tests") set.seed(6) obs3 <- rnorm(10) + # case 4 + set.seed(7) + exp4 <- array(rnorm(120), dim = c(sdate = 10, dat = 1, lon = 3, lat = 2)) + set.seed(8) + obs4 <- array(rnorm(60), dim = c(dat = 1, sdate = 10, lat = 2, lon = 3)) + ############################################## test_that("1. Input checks", { @@ -64,7 +70,8 @@ test_that("1. Input checks", { ) expect_error( RMSSS(exp0, obs0, dat_dim = 'memb'), - "Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension." + paste0("Parameter 'dat_dim' is not found in 'exp' or 'obs' dimension.", + " Set it as NULL if there is no dataset dimension.") ) expect_error( RMSSS(exp0, obs0, pval = c(T, T)), @@ -77,7 +84,7 @@ test_that("1. Input checks", { expect_error( RMSSS(exp = array(1:10, dim = c(sdate = 1, dataset = 5, a = 1)), obs = array(1:4, dim = c(a = 1, sdate = 2, dataset = 2))), - "Parameter 'exp' and 'obs' must have same length of all dimension expect 'dat_dim'." + "Parameter 'exp' and 'obs' must have same length of all dimension except 'dat_dim'." ) expect_error( RMSSS(exp = array(1:10, dim = c(sdate = 1, dataset = 5, a = 1)), @@ -157,5 +164,24 @@ test_that("4. Output checks: case 3", { tolerance = 0.00001 ) +}) + +############################################## +test_that("5. Output checks: case 4", { + + expect_equal( + dim(RMSSS(exp4, obs4, dat_dim = NULL)$rmsss), + c(dat = 1, lon = 3, lat = 2) + ) + expect_equal( + mean(RMSSS(exp4, obs4, dat_dim = NULL)$rmsss), + -0.3114424, + tolerance = 0.00001 + ) + expect_equal( + range(RMSSS(exp4, obs4, dat_dim = NULL)$p.val), + c(0.3560534, 0.9192801), + tolerance = 0.00001 + ) }) diff --git a/tests/testthat/test-RPS.R b/tests/testthat/test-RPS.R index 04df1bb397b6906c10a16a5be1f92c1858299103..2029fd981b8efeb13ad18ddb4def4e596c6d37e6 100644 --- a/tests/testthat/test-RPS.R +++ b/tests/testthat/test-RPS.R @@ -56,7 +56,7 @@ test_that("1. Input checks", { # exp, ref, and obs (2) expect_error( RPS(exp1, array(1:9, dim = c(sdate = 9))), - "Parameter 'exp' and 'obs' must have same length of all dimensions expect 'memb_dim'." + "Parameter 'exp' and 'obs' must have same length of all dimensions except 'memb_dim'." ) # prob_thresholds expect_error( diff --git a/tests/testthat/test-RPSS.R b/tests/testthat/test-RPSS.R index c63add02246ef4980a8c388bed7b54a239e62d24..b8623b6e82cce7d8721a82a4bb4f19fcf2239651 100644 --- a/tests/testthat/test-RPSS.R +++ b/tests/testthat/test-RPSS.R @@ -63,11 +63,11 @@ test_that("1. Input checks", { # exp, ref, and obs (2) expect_error( RPSS(exp1, array(1:9, dim = c(sdate = 9))), - "Parameter 'exp' and 'obs' must have same length of all dimensions expect 'memb_dim'." + "Parameter 'exp' and 'obs' must have same length of all dimensions except 'memb_dim'." ) expect_error( RPSS(exp1, obs1, ref2), - "Parameter 'exp' and 'obs' must have same length of all dimensions expect 'memb_dim'." + "Parameter 'exp' and 'obs' must have same length of all dimensions except 'memb_dim'." ) # prob_thresholds expect_error( diff --git a/tests/testthat/test-RatioSDRMS.R b/tests/testthat/test-RatioSDRMS.R index 4b93fafa213dcac0e831b7ac59d7646064f8f856..5dbc171337d4bec4fe9db6e2c491ec527511efc3 100644 --- a/tests/testthat/test-RatioSDRMS.R +++ b/tests/testthat/test-RatioSDRMS.R @@ -77,7 +77,7 @@ test_that("1. Input checks", { expect_error( RatioSDRMS(exp = exp3, obs = array(1:2, dim = c(member = 1, sdate = 2)), dat_dim = NULL), - "Parameter 'exp' and 'obs' must have same length of all the dimensions expect 'dat_dim' and 'memb_dim'." + "Parameter 'exp' and 'obs' must have same length of all the dimensions except 'dat_dim' and 'memb_dim'." ) }) diff --git a/tests/testthat/test-ResidualCorr.R b/tests/testthat/test-ResidualCorr.R index c15276c93368322eec48e8b33657474fb8f4a1c4..be71b4748295f70ddc43f7c3d3bccdf1d1f60100 100644 --- a/tests/testthat/test-ResidualCorr.R +++ b/tests/testthat/test-ResidualCorr.R @@ -66,7 +66,7 @@ test_that("1. Input checks", { # exp, ref, and obs (2) expect_error( ResidualCorr(exp1, obs1, array(1:10, dim = c(sdate = 10, memb = 1)), memb_dim = 'memb'), - "Parameter 'exp', 'obs', and 'ref' must have same length of all dimensions expect 'memb_dim'." + "Parameter 'exp', 'obs', and 'ref' must have same length of all dimensions except 'memb_dim'." ) # method expect_error( diff --git a/tests/testthat/test-UltimateBrier.R b/tests/testthat/test-UltimateBrier.R index 654aad020d5d7df65981316ab1918b3cece94c51..09412f00cf1ce52265328f9da89f2f404081877a 100644 --- a/tests/testthat/test-UltimateBrier.R +++ b/tests/testthat/test-UltimateBrier.R @@ -7,7 +7,11 @@ exp1 <- array(rnorm(30), dim = c(dataset = 1, member = 3, sdate = 5, ftime = 2)) set.seed(2) obs1 <- array(round(rnorm(10)), dim = c(dataset = 1, sdate = 5, ftime = 2)) - +# dat2 +set.seed(1) +exp2 <- array(rnorm(30), dim = c(member = 3, sdate = 5, ftime = 2)) +set.seed(2) +obs2 <- array(round(rnorm(10)), dim = c(sdate = 5, ftime = 2)) ############################################## test_that("1. Input checks", { # exp and obs @@ -26,7 +30,7 @@ test_that("1. Input checks", { # dat_dim expect_error( UltimateBrier(exp1, obs1, dat_dim = 2), - "Parameter 'dat_dim' must be a character string." + "Parameter 'dat_dim' must be a character string or NULL." ) expect_error( UltimateBrier(exp1, obs1, dat_dim = 'dat'), @@ -58,12 +62,12 @@ test_that("1. Input checks", { expect_error( UltimateBrier(exp1, array(1:10, dim = c(dataset = 1, sdate = 6, ftime = 2))), paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'dat_dim' and 'memb_dim'.") + "of all the dimensions except 'dat_dim' and 'memb_dim'.") ) expect_error( UltimateBrier(exp1, array(1:10, dim = c(dataset = 1, sdate = 5, time = 2))), paste0("Parameter 'exp' and 'obs' must have the same names and lengths ", - "of all the dimensions expect 'dat_dim' and 'memb_dim'.") + "of all the dimensions except 'dat_dim' and 'memb_dim'.") ) # quantile expect_error( @@ -105,136 +109,269 @@ test_that("1. Input checks", { ############################################## test_that("2. Output checks: dat1", { -# 'BS' -expect_equal( -is.list(UltimateBrier(exp1, obs1)), -TRUE -) -expect_equal( -names(UltimateBrier(exp1, obs1)), -c('bs', 'rel', 'res', 'unc') -) -expect_equal( -is.list(UltimateBrier(exp1, obs1, decomposition = FALSE)), -FALSE -) -expect_equal( -dim(UltimateBrier(exp1, obs1, decomposition = FALSE)), -c(nexp = 1, nobs = 1, bin = 3, ftime = 2) -) -expect_equal( -dim(UltimateBrier(exp1, obs1, decomposition = FALSE, thr = c(0.25, 0.5, 0.75))), -c(nexp = 1, nobs = 1, bin = 4, ftime = 2) -) -expect_equal( -UltimateBrier(exp1, obs1)$bs, -UltimateBrier(exp1, obs1, decomposition = FALSE) -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1)$bs), -c(0.42222222, 0.44444444, 0.02222222, 0.48888889, 0.37777778, 0.02222222), -tolerance = 0.0001 -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1)$rel), -c(0.22222222, 0.31111111, 0.02222222, 0.28888889, 0.24444444, 0.02222222), -tolerance = 0.0001 -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1)$res), -c(0.0400000, 0.1066667, 0.0000000, 0.0400000, 0.1066667, 0.0000000), -tolerance = 0.0001 -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1)$unc), -c(0.24, 0.24, 0.00, 0.24, 0.24, 0.00), -tolerance = 0.0001 -) - -# 'BSS' -expect_equal( -dim(UltimateBrier(exp1, obs1, type = 'BSS')), -c(nexp = 1, nobs = 1, bin = 3, ftime = 2) -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1, type = 'BSS')), -c(-0.7592593, -0.8518519, -Inf, -1.0370370, -0.5740741, -Inf), -tolerance = 0.0001 -) - -# 'FairStartDatesBS' -expect_equal( -is.list(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')), -TRUE -) -expect_equal( -names(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')), -c('bs', 'rel', 'res', 'unc') -) -expect_equal( -is.list(UltimateBrier(exp1, obs1, decomposition = FALSE, type = 'FairStartDatesBS')), -FALSE -) -expect_equal( -dim(UltimateBrier(exp1, obs1, decomposition = FALSE, type = 'FairStartDatesBS')), -c(nexp = 1, nobs = 1, bin = 3, ftime = 2) -) -expect_equal( -UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$bs, -UltimateBrier(exp1, obs1, decomposition = FALSE, type = 'FairStartDatesBS') -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$bs), -c(0.42222222, 0.44444444, 0.02222222, 0.48888889, 0.37777778, 0.02222222), -tolerance = 0.0001 -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$rel), -c(0.22222222, 0.31111111, 0.02222222, 0.28888889, 0.24444444, 0.02222222), -tolerance = 0.0001 -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$res), -c(0.0400000, 0.1066667, 0.0000000, 0.0400000, 0.1066667, 0.0000000), -tolerance = 0.0001 -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$unc), -c(0.24, 0.24, 0.00, 0.24, 0.24, 0.00), -tolerance = 0.0001 -) - -# 'FairStartDatesBSS' -expect_equal( -dim(UltimateBrier(exp1, obs1, type = 'FairStartDatesBSS')), -c(nexp = 1, nobs = 1, bin = 3, ftime = 2) -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBSS')), -c(-0.7592593, -0.8518519, -Inf, -1.0370370, -0.5740741, -Inf), -tolerance = 0.0001 -) -# 'FairEnsembleBS' -expect_equal( -dim(UltimateBrier(exp1, obs1, type = 'FairEnsembleBS')), -c(nexp = 1, nobs = 1, bin = 3, ftime = 2) -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1, type = 'FairEnsembleBS')), -c(0.1333333, 0.2000000, 0.2000000, 0.1333333, 0.4000000, 0.2000000), -tolerance = 0.0001 -) -# 'FairEnsembleBSS' -expect_equal( -dim(UltimateBrier(exp1, obs1, type = 'FairEnsembleBSS')), -c(nexp = 1, nobs = 1, bin = 3, ftime = 2) -) -expect_equal( -as.vector(UltimateBrier(exp1, obs1, type = 'FairEnsembleBSS')), -c(-0.1111111, -0.6666667, -0.6666667, 0.2592593, -1.2222222, -0.6666667), -tolerance = 0.0001 -) + # 'BS' + expect_equal( + is.list(UltimateBrier(exp1, obs1)), + TRUE + ) + expect_equal( + names(UltimateBrier(exp1, obs1)), + c('bs', 'rel', 'res', 'unc') + ) + expect_equal( + is.list(UltimateBrier(exp1, obs1, decomposition = FALSE)), + FALSE + ) + expect_equal( + dim(UltimateBrier(exp1, obs1, decomposition = FALSE)), + c(nexp = 1, nobs = 1, bin = 3, ftime = 2) + ) + expect_equal( + dim(UltimateBrier(exp1, obs1, decomposition = FALSE, thr = c(0.25, 0.5, 0.75))), + c(nexp = 1, nobs = 1, bin = 4, ftime = 2) + ) + expect_equal( + UltimateBrier(exp1, obs1)$bs, + UltimateBrier(exp1, obs1, decomposition = FALSE) + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1)$bs), + c(0.42222222, 0.44444444, 0.02222222, 0.48888889, 0.37777778, 0.02222222), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1)$rel), + c(0.22222222, 0.31111111, 0.02222222, 0.28888889, 0.24444444, 0.02222222), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1)$res), + c(0.0400000, 0.1066667, 0.0000000, 0.0400000, 0.1066667, 0.0000000), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1)$unc), + c(0.24, 0.24, 0.00, 0.24, 0.24, 0.00), + tolerance = 0.0001 + ) + + # 'BSS' + expect_equal( + dim(UltimateBrier(exp1, obs1, type = 'BSS')), + c(nexp = 1, nobs = 1, bin = 3, ftime = 2) + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1, type = 'BSS')), + c(-0.7592593, -0.8518519, -Inf, -1.0370370, -0.5740741, -Inf), + tolerance = 0.0001 + ) + + # 'FairStartDatesBS' + expect_equal( + is.list(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')), + TRUE + ) + expect_equal( + names(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')), + c('bs', 'rel', 'res', 'unc') + ) + expect_equal( + is.list(UltimateBrier(exp1, obs1, decomposition = FALSE, type = 'FairStartDatesBS')), + FALSE + ) + expect_equal( + dim(UltimateBrier(exp1, obs1, decomposition = FALSE, type = 'FairStartDatesBS')), + c(nexp = 1, nobs = 1, bin = 3, ftime = 2) + ) + expect_equal( + UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$bs, + UltimateBrier(exp1, obs1, decomposition = FALSE, type = 'FairStartDatesBS') + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$bs), + c(0.42222222, 0.44444444, 0.02222222, 0.48888889, 0.37777778, 0.02222222), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$rel), + c(0.22222222, 0.31111111, 0.02222222, 0.28888889, 0.24444444, 0.02222222), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$res), + c(0.0400000, 0.1066667, 0.0000000, 0.0400000, 0.1066667, 0.0000000), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBS')$unc), + c(0.24, 0.24, 0.00, 0.24, 0.24, 0.00), + tolerance = 0.0001 + ) + + # 'FairStartDatesBSS' + expect_equal( + dim(UltimateBrier(exp1, obs1, type = 'FairStartDatesBSS')), + c(nexp = 1, nobs = 1, bin = 3, ftime = 2) + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1, type = 'FairStartDatesBSS')), + c(-0.7592593, -0.8518519, -Inf, -1.0370370, -0.5740741, -Inf), + tolerance = 0.0001 + ) + # 'FairEnsembleBS' + expect_equal( + dim(UltimateBrier(exp1, obs1, type = 'FairEnsembleBS')), + c(nexp = 1, nobs = 1, bin = 3, ftime = 2) + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1, type = 'FairEnsembleBS')), + c(0.1333333, 0.2000000, 0.2000000, 0.1333333, 0.4000000, 0.2000000), + tolerance = 0.0001 + ) + # 'FairEnsembleBSS' + expect_equal( + dim(UltimateBrier(exp1, obs1, type = 'FairEnsembleBSS')), + c(nexp = 1, nobs = 1, bin = 3, ftime = 2) + ) + expect_equal( + as.vector(UltimateBrier(exp1, obs1, type = 'FairEnsembleBSS')), + c(-0.1111111, -0.6666667, -0.6666667, 0.2592593, -1.2222222, -0.6666667), + tolerance = 0.0001 + ) }) +############################################## +test_that("3. Output checks: dat2", { + # 'BS' + expect_equal( + is.list(UltimateBrier(exp2, obs2, dat_dim = NULL)), + TRUE + ) + expect_equal( + names(UltimateBrier(exp2, obs2, dat_dim = NULL)), + c('bs', 'rel', 'res', 'unc') + ) + expect_equal( + is.list(UltimateBrier(exp2, obs2, dat_dim = NULL, decomposition = FALSE)), + FALSE + ) + expect_equal( + dim(UltimateBrier(exp2, obs2, dat_dim = NULL, decomposition = FALSE)), + c(bin = 3, ftime = 2) + ) + expect_equal( + dim(UltimateBrier(exp2, obs2, dat_dim = NULL, decomposition = FALSE, thr = c(0.25, 0.5, 0.75))), + c(bin = 4, ftime = 2) + ) + expect_equal( + UltimateBrier(exp2, obs2, dat_dim = NULL)$bs, + UltimateBrier(exp2, obs2, dat_dim = NULL, decomposition = FALSE) + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL)$bs), + c(0.42222222, 0.44444444, 0.02222222, 0.48888889, 0.37777778, 0.02222222), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL)$rel), + c(0.22222222, 0.31111111, 0.02222222, 0.28888889, 0.24444444, 0.02222222), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL)$res), + c(0.0400000, 0.1066667, 0.0000000, 0.0400000, 0.1066667, 0.0000000), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL)$unc), + c(0.24, 0.24, 0.00, 0.24, 0.24, 0.00), + tolerance = 0.0001 + ) + + # 'BSS' + expect_equal( + dim(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'BSS')), + c(bin = 3, ftime = 2) + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'BSS')), + c(-0.7592593, -0.8518519, -Inf, -1.0370370, -0.5740741, -Inf), + tolerance = 0.0001 + ) + + # 'FairStartDatesBS' + expect_equal( + is.list(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBS')), + TRUE + ) + expect_equal( + names(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBS')), + c('bs', 'rel', 'res', 'unc') + ) + expect_equal( + is.list(UltimateBrier(exp2, obs2, dat_dim = NULL, decomposition = FALSE, type = 'FairStartDatesBS')), + FALSE + ) + expect_equal( + dim(UltimateBrier(exp2, obs2, dat_dim = NULL, decomposition = FALSE, type = 'FairStartDatesBS')), + c(bin = 3, ftime = 2) + ) + expect_equal( + UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBS')$bs, + UltimateBrier(exp2, obs2, dat_dim = NULL, decomposition = FALSE, type = 'FairStartDatesBS') + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBS')$bs), + c(0.42222222, 0.44444444, 0.02222222, 0.48888889, 0.37777778, 0.02222222), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBS')$rel), + c(0.22222222, 0.31111111, 0.02222222, 0.28888889, 0.24444444, 0.02222222), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBS')$res), + c(0.0400000, 0.1066667, 0.0000000, 0.0400000, 0.1066667, 0.0000000), + tolerance = 0.0001 + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBS')$unc), + c(0.24, 0.24, 0.00, 0.24, 0.24, 0.00), + tolerance = 0.0001 + ) + + # 'FairStartDatesBSS' + expect_equal( + dim(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBSS')), + c(bin = 3, ftime = 2) + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairStartDatesBSS')), + c(-0.7592593, -0.8518519, -Inf, -1.0370370, -0.5740741, -Inf), + tolerance = 0.0001 + ) + # 'FairEnsembleBS' + expect_equal( + dim(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairEnsembleBS')), + c(bin = 3, ftime = 2) + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairEnsembleBS')), + c(0.1333333, 0.2000000, 0.2000000, 0.1333333, 0.4000000, 0.2000000), + tolerance = 0.0001 + ) + # 'FairEnsembleBSS' + expect_equal( + dim(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairEnsembleBSS')), + c(bin = 3, ftime = 2) + ) + expect_equal( + as.vector(UltimateBrier(exp2, obs2, dat_dim = NULL, type = 'FairEnsembleBSS')), + c(-0.1111111, -0.6666667, -0.6666667, 0.2592593, -1.2222222, -0.6666667), + tolerance = 0.0001 + ) + +})