Nothing
# File quant2ecdf.R
# Part of the hydroPSO R package, https://github.com/hzambran/hydroPSO
# http://cran.r-project.org/web/packages/hydroPSO
# http://www.rforge.net/hydroPSO/
# Copyright 2010-2020 Mauricio Zambrano-Bigiarini & Rodrigo Rojas
# Distributed under GPL 2 or later
################################################################################
# 'quant2ecdf' #
################################################################################
# Purpose: This function computes ECDFs for user-defined quantiles of the #
# streamflows simulated with different behavioural parameter sets, #
# with optional plot #
################################################################################
# Author : Mauricio Zambrano-Bigiarini #
# Started: June 28th, 2010 #
# Updates: 01-Dec-2010 #
# 28-Jan-2011 ; 13-Feb-2011 ; 27-Apr-2011 ; 12-Oct-2011 #
# 15-Feb-2012 ; 29-Nov-2012 #
# 26-Feb-2020 #
################################################################################
# Steps:
# 1) it computes un-weighted quantiles (e.g., Q5, Q50, Q95) for the
# streamflows simulated with EACH behavioural parameter set
# 2) it computes ECDFs for each desired quantile, by weighting the quantile
# of each behavioural parameter set by its corresponding less-formal likelihood
# sim : matrix with the behavioural model ouputs
# obs : vector with the observed values
# weights: numeric vector, with the values of the weights to be used for computing the quantiles. \cr
# Omitting the \code{weights} argument or specifying \code{NULL} or a zero-length vector will result in the usual unweighted estimates.
# byrow : logical, indicating if the computations have to be made for each column or for each row of \code{x}.
# When the simulated values obtained with different behavioural parameter sets are stored in columns, \code{byrow} must be \kbd{TRUE}. \cr
# When the simulated values obtained with different behavioural parameter sets are stored in rows, \code{byrow} must be \kbd{FALSE}.
quant2ecdf <-function(sim, ...) UseMethod("quant2ecdf")
quant2ecdf.default <- function(sim,
weights=NULL,
byrow=TRUE,
quantiles.desired= c(0.05, 0.5, 0.95),
plot=TRUE,
obs=NULL,
quantiles.labels= c("Q5", "Q50", "Q95"),
main=NULL,
ylab="Probability",
col="blue",
leg.cex=1.2,
leg.pos="bottomright",
cex.axis=1.2,
cex.main=1.2,
cex.lab=1.2,
verbose=TRUE,
...
) {
if ( !( is(sim, "matrix") | is(sim, "data.frame") ) )
stop("Invalid argument: 'class(sim)' must be in c('matrix', 'data.frame')")
# Unweighted quantiles (usually, Q5, Q50, Q95).
# Due to the fact that 'weights' is missing, and its default value
# is NULL, the computation returns un-weighted quantiles
ifelse(byrow==TRUE, stg <- "ROW", stg <- "COLUMN")
if (verbose) message( "[ Computing un-weighted quantiles for each ", stg, " of 'sim' ... ]" )
q5.50.95 <- wquantile(sim, byrow=byrow, probs=quantiles.desired)
# number of desired quantiles, usually 3
nquantiles <- length(quantiles.desired)
# creating the final output, a list with the ECDFs
ecdf <- vector("list", nquantiles)
if (plot) {
# Saving default plotting parameters
old.par <- par(no.readonly=TRUE)
#if (!do.png) on.exit(par(old.par))
par(mfrow=c(1,nquantiles))
if (!is.null(main)) par(oma=c(1,1,3,0))
} # IF end
########################### MAIN LOOP ##################################
ifelse(is.null(weights), stg <- "the UN-weighted", stg <- "the weighted")
for ( i in 1:nquantiles ) {
if (verbose) message("[ Computing ", stg, " ECDF for quantile ",
format(quantiles.desired[i], width=5, justify="left"),
" , ", i, "/", nquantiles, "=>",
format(round(100*i/nquantiles, 2), width=7, justify="left"),
"% ... ]" )
# Weighted ECDF for the "i-th" desired quantile, where the unweighted
# 'i-th' quantile of each behavioural parameter set is now weighted by the
# weights given by 'w' (usually, the normalized less-formal likelihood)
x.ecdf <- Hmisc::wtd.Ecdf(q5.50.95[, i], weights = weights, normwt=TRUE)
ecdf[[i]] <- x.ecdf
names(ecdf)[i] <- quantiles.labels[i]
if (plot) {
if ( !is.null(obs) & is.numeric(obs) ) {
if (is.na(match(class(obs), c("zoo", "numeric", "integer") ) ) )
stop("Invalid argument: 'class(obs)' must be in c('zoo', 'numeric', 'integer')")
# Observed quantile (Q5, Q50, Q95) during the calibration period
quantile.obs <- quantile(as.numeric(obs), probs=quantiles.desired[i], na.rm=TRUE)
} # IF end
# plot label for each ECDF
main.loc <- paste("Empirical CDF of", quantiles.labels[i], sep=" ")
# Drawing the plotting the area, but without Y-axis
plot(x.ecdf$x, x.ecdf$ecdf, xlab= paste(quantiles.labels[i], "[m3/s]", sep=" "),
col=col, yaxt = "n", type="b", cex=0.2, main=main.loc, ylab=ylab,
cex.axis=cex.axis, cex.main=cex.main, cex.lab=cex.lab, font.lab=2, ... )
# Drawing the labels in the 'y' axis
Axis(side = 2, at = seq(0.0, 1, by=0.05), labels = FALSE,
cex.axis=cex.axis, cex.lab=cex.lab)
Axis(side = 2, at = seq(0.0, 1, by=0.1), labels = seq(0.0, 1, by=0.1),
cex.axis=cex.axis, cex.lab=cex.lab, font.lab=2)
# Drawing a vertical line on the observed quantile Q5, Q50, Q95
if ( !is.null(obs) & is.numeric(obs) )
abline(v=quantile.obs, lty=3, col="black", lwd=2)
# Drawing an horizontal line on Probability = 0.5
abline(h=0.5, lty=2, col="grey", lwd=2)
# Computing a function that give the 'x' value that corresponds to a
# given value of cdf, by using linear interpolation
f <- approxfun(x.ecdf$ecdf, x.ecdf$x)
# Quantile corresponding to a cdf=0.5
quantile.sim <- f(0.5)
# Drawing a vertical line on the simulated quantile Q5, Q50, Q95
abline(v=quantile.sim, lty=3, col="grey", lwd=2)
# Bias of the simulated streamflows, in percentage [%]
if ( !is.null(obs) & is.numeric(obs) ) {
bias <- 100 * (quantile.sim - quantile.obs) / quantile.obs
if (bias == 0) txt.col <- "green"
if (bias < 0) txt.col <- "red"
if (bias > 0) txt.col <- "blue"
# Presenting the value of the observed Q5 as a legend
leg.txt <- c( paste(quantiles.labels[i], "obs= ", round(quantile.obs,2) ) ,
paste(quantiles.labels[i], "sim= ", round(quantile.sim,2) ),
paste("Bias=", round(bias,1), "[%]", sep=" " ) )
legend(leg.pos, legend=leg.txt, inset=0.02, bty="n",
cex =leg.cex, text.col=c("black", "black", txt.col))
} else {
leg.txt <- paste(quantiles.labels[i], "sim= ", round(quantile.sim,3) )
legend(leg.pos, legend=leg.txt, bty="n", cex=leg.cex)
} # ELSE end
} # IF end
} # FOR end
if (plot) {
# Adding a main title for the plot
if (!is.null(main)) mtext(main, side=3, line=1, cex=cex.main, outer=TRUE)
} # IF end
return(ecdf)
} # END 'quant2ecdf.default'
################################################################################
# Author : Mauricio Zambrano-Bigiarini #
# Started: 12-Oct-2011 #
# Updates: 12-Oct-2011 #
################################################################################
quant2ecdf.matrix <- function(sim,
weights=NULL,
byrow=TRUE,
quantiles.desired= c(0.05, 0.5, 0.95),
plot=TRUE,
obs=NULL,
quantiles.labels= c("Q5", "Q50", "Q95"),
main=NULL,
ylab="Probability",
col="blue",
leg.cex=1.2,
leg.pos="bottomright",
cex.axis=1.2,
cex.main=1.2,
cex.lab=1.2,
verbose=TRUE,
...
) {
quant2ecdf.default(sim=sim,
weights=weights,
byrow=byrow,
quantiles.desired=quantiles.desired,
plot=plot,
obs=obs,
quantiles.labels= quantiles.labels,
main=main,
ylab=ylab,
col=col,
leg.cex=leg.cex,
leg.pos=leg.pos,
cex.axis=cex.axis,
cex.main=cex.main,
cex.lab=cex.lab,
verbose=verbose,
...
)
} # 'quant2ecdf.matrix' END
################################################################################
# Author : Mauricio Zambrano-Bigiarini #
# Started: 12-Oct-2011 #
# Updates: 12-Oct-2011 #
###############################################################################
quant2ecdf.data.frame <- function(sim,
weights=NULL,
byrow=TRUE,
quantiles.desired= c(0.05, 0.5, 0.95),
plot=TRUE,
obs=NULL,
quantiles.labels= c("Q5", "Q50", "Q95"),
main=NULL,
ylab="Probability",
col="blue",
leg.cex=1.2,
leg.pos="bottomright",
cex.axis=1.2,
cex.main=1.2,
cex.lab=1.2,
verbose=TRUE,
...
) {
sim <- as.matrix(sim)
quant2ecdf.matrix(sim=sim,
weights=weights,
byrow=byrow,
quantiles.desired=quantiles.desired,
plot=plot,
obs=obs,
quantiles.labels= quantiles.labels,
main=main,
ylab=ylab,
col=col,
leg.cex=leg.cex,
leg.pos=leg.pos,
cex.axis=cex.axis,
cex.main=cex.main,
cex.lab=cex.lab,
verbose=verbose,
...
)
} # 'quant2ecdf.data.frame' END
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.