diff --git a/.Rbuildignore b/.Rbuildignore index 88a083344290395ebb1b3f767616fcb2bdc82cf4..7c1c5baa8f03668a04b8d352020ed07372de4599 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -7,3 +7,4 @@ ^\.regressionignore$ ^\.gitlab-ci\.yml$ ^\.vscode$ +^Rplots\.pdf$ diff --git a/DESCRIPTION b/DESCRIPTION index bb56081c41492df3752ffdbfd7ff6cf2a51a4e27..3664b2bae3712d7fb61502e5862c3714231ea657 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: airGR Type: Package Title: Suite of GR Hydrological Models for Precipitation-Runoff Modelling -Version: 1.6.8.20 +Version: 1.6.8.21 Date: 2020-12-01 Authors@R: c( person("Laurent", "Coron", role = c("aut", "trl"), comment = c(ORCID = "0000-0002-1503-6204")), @@ -20,7 +20,7 @@ Authors@R: c( person("Raji", "Pushpalatha", role = c("ctb")), person("Audrey", "Valéry", role = c("ctb")) ) -Depends: R (>= 3.0.1) +Depends: R (>= 3.1.0) Suggests: knitr, rmarkdown, coda, DEoptim, dplyr, FME, ggmcmc, hydroPSO, Rmalschains, testthat, imputeTS Description: Hydrological modelling tools developed at INRAE-Antony (HYCAR Research Unit, France). The package includes several conceptual rainfall-runoff models (GR4H, GR5H, GR4J, GR5J, GR6J, GR2M, GR1A), a snow accumulation and melt model (CemaNeige) and the associated functions for their calibration and evaluation. Use help(airGR) for package description and references. License: GPL-2 diff --git a/R/SeriesAggreg.InputsModel.R b/R/SeriesAggreg.InputsModel.R index 53cbcc1f72e559df1ccb6676b863eaa375552e95..68c095ee2a10df44b13ecb1c99325fa71667bfb7 100644 --- a/R/SeriesAggreg.InputsModel.R +++ b/R/SeriesAggreg.InputsModel.R @@ -1,12 +1,6 @@ -SeriesAggreg.InputsModel <- function(TabSeries, ...) { - if (!inherits(TabSeries, "InputsModel")) { - stop("to be used with 'InputsModel' object") - } - res <- - SeriesAggreg.list(TabSeries, - except = c("ZLayers", "LengthHydro", "BasinAreas"), - ...) - +SeriesAggreg.InputsModel <- function(x, ...) { + res <- SeriesAggreg.list(x, + except = c("ZLayers", "LengthHydro", "BasinAreas"), + ...) return(res) - } diff --git a/R/SeriesAggreg.OutputsModel.R b/R/SeriesAggreg.OutputsModel.R index d370fcc7fbff4432cb1a8c3434454da8d58e0ce3..dae7256ddde8723a24f3e8b4c2a38f629e38b243 100644 --- a/R/SeriesAggreg.OutputsModel.R +++ b/R/SeriesAggreg.OutputsModel.R @@ -1,11 +1,4 @@ -SeriesAggreg.OutputsModel <- function(TabSeries, ...) { - - if (!inherits(TabSeries, "OutputsModel")) { - stop("to be used with 'OutputsModel' object") - } - - res <- SeriesAggreg.list(TabSeries, except = "StateEnd", ...) - +SeriesAggreg.OutputsModel <- function(x, ...) { + res <- SeriesAggreg.list(x, except = "StateEnd", ...) return(res) - -} \ No newline at end of file +} diff --git a/R/SeriesAggreg.R b/R/SeriesAggreg.R index b4fd59fd619e8b17da1f4c9de8d8e6a9d86dbc92..737ce62eb7840cc38b59fad260c1d07bf150fc45 100644 --- a/R/SeriesAggreg.R +++ b/R/SeriesAggreg.R @@ -1,3 +1,3 @@ -SeriesAggreg <- function(TabSeries, Format, ...) { +SeriesAggreg <- function(x, Format, ...) { UseMethod("SeriesAggreg") } diff --git a/R/SeriesAggreg.data.frame.R b/R/SeriesAggreg.data.frame.R index 1b4c102035a213f18dc24f8c4b19d71fd4869192..ad37d16b08bb85b049ec5c1d96811dd09934ff0d 100644 --- a/R/SeriesAggreg.data.frame.R +++ b/R/SeriesAggreg.data.frame.R @@ -1,6 +1,6 @@ -SeriesAggreg.data.frame <- function(TabSeries, +SeriesAggreg.data.frame <- function(x, Format, - ConvertFun = getAggregConvertFun(names(TabSeries)[-1]), + ConvertFun = getAggregConvertFun(names(x)[-1]), TimeFormat = NULL, NewTimeFormat = NULL, YearFirstMonth = 1, @@ -20,27 +20,27 @@ SeriesAggreg.data.frame <- function(TabSeries, stop("argument 'Format' is missing") } - ## check TabSeries - if (!is.data.frame(TabSeries)) { - stop("'TabSeries' must be a data.frame containing the dates and data to be aggregated") + ## check x + if (!is.data.frame(x)) { + stop("'x' must be a data.frame containing the dates and data to be aggregated") } - if (ncol(TabSeries) < 2) { - stop("'TabSeries' must contain at least two columns (including the column of dates)") + if (ncol(x) < 2) { + stop("'x' must contain at least two columns (including the column of dates)") } - ## check TabSeries date column - if (!inherits(TabSeries[[1L]], "POSIXt")) { - stop("'TabSeries' first column must be a vector of class 'POSIXlt' or 'POSIXct'") + ## check x date column + if (!inherits(x[[1L]], "POSIXt")) { + stop("'x' first column must be a vector of class 'POSIXlt' or 'POSIXct'") } - if (inherits(TabSeries[[1L]], "POSIXlt")) { - TabSeries[[1L]] <- as.POSIXct(TabSeries[[1L]]) + if (inherits(x[[1L]], "POSIXlt")) { + x[[1L]] <- as.POSIXct(x[[1L]]) } - ## check TabSeries other columns (boolean converted to numeric) + ## check x other columns (boolean converted to numeric) apply( - TabSeries[, -1L, drop = FALSE], + x[, -1L, drop = FALSE], MARGIN = 2, FUN = function(iCol) { if (!is.numeric(iCol)) { - stop("'TabSeries' columns (other than the first one) must be of numeric class") + stop("'x' columns (other than the first one) must be of numeric class") } } ) @@ -57,10 +57,10 @@ SeriesAggreg.data.frame <- function(TabSeries, if (anyNA(ConvertFun)) { stop("'ConvertFun' should be a one of 'sum' or 'mean'") } - if (length(ConvertFun) != (ncol(TabSeries) - 1)) { + if (length(ConvertFun) != (ncol(x) - 1)) { stop(sprintf( - "'ConvertFun' must be of length %i (ncol(TabSeries)-1)", - ncol(TabSeries) - 1 + "'ConvertFun' must be of length %i (ncol(x)-1)", + ncol(x) - 1 )) } ## check YearFirstMonth @@ -89,8 +89,7 @@ SeriesAggreg.data.frame <- function(TabSeries, stop(msgTimeLag) } - - TabSeries0 <- TabSeries + TabSeries0 <- x colnames(TabSeries0)[1L] <- "DatesR" TabSeries0$DatesR <- TabSeries0$DatesR + TimeLag @@ -105,7 +104,7 @@ SeriesAggreg.data.frame <- function(TabSeries, 1) by <- ifelse(grepl("hours", format(diff( - TabSeries$DatesR[1:2] + x$DatesR[1:2] ))), yes = "hours", no = "days") fakeTs <- data.frame(DatesR = seq( @@ -126,9 +125,9 @@ SeriesAggreg.data.frame <- function(TabSeries, TabSeries2$Selec <- !duplicated(TabSeries2$Selec2) if (all(TabSeries2$Selec)) { warning( - "the requested time 'Format' is the same as the one in 'TabSeries'. No time-step conversion was performed" + "the requested time 'Format' is the same as the one in 'x'. No time-step conversion was performed" ) - return(TabSeries) + return(x) } if (Format == "%Y") { yfm <- sprintf("%02.f", YearFirstMonth) @@ -148,16 +147,16 @@ SeriesAggreg.data.frame <- function(TabSeries, } TabSeries2$Fac2 <- TabSeries2$Selec2 TabSeries2$Selec <- !duplicated(TabSeries2$Selec2) - ConvertFun <- rep("mean", ncol(TabSeries) - 1) + ConvertFun <- rep("mean", ncol(x) - 1) } - #browser() - listTsAggreg <- lapply(names(listConvertFun), function(x) { - if (any(ConvertFun == x)) { + + listTsAggreg <- lapply(names(listConvertFun), function(y) { + if (any(ConvertFun == y)) { colTsAggreg <- - c("Fac2", colnames(TabSeries)[-1L][ConvertFun == x]) + c("Fac2", colnames(x)[-1L][ConvertFun == y]) aggregate(. ~ Fac2, data = TabSeries2[, colTsAggreg], - FUN = listConvertFun[[x]], + FUN = listConvertFun[[y]], na.action = na.pass) } else { NULL diff --git a/R/SeriesAggreg.list.R b/R/SeriesAggreg.list.R index 806736634f1206c95a14370eb3ed034eb8ad7f71..5152f4d245b67b3911c1f28046cc34cd0418813d 100644 --- a/R/SeriesAggreg.list.R +++ b/R/SeriesAggreg.list.R @@ -1,4 +1,4 @@ -SeriesAggreg.list <- function(TabSeries, +SeriesAggreg.list <- function(x, Format, ConvertFun, NewTimeFormat = NULL, @@ -6,10 +6,6 @@ SeriesAggreg.list <- function(TabSeries, except = NULL, recursive = TRUE, ...) { - if (!is.list(TabSeries)) { - stop("to be used with a list") - } - if (missing(Format)) { Format <- getSeriesAggregFormat(NewTimeFormat) } else if (!is.null(NewTimeFormat)) { @@ -18,31 +14,31 @@ SeriesAggreg.list <- function(TabSeries, } # Determination of DatesR - if (!is.null(TabSeries$DatesR)) { - if (!inherits(TabSeries$DatesR, "POSIXt")) { - stop("'TabSeries$DatesR' should be of class 'POSIXt'") + if (!is.null(x$DatesR)) { + if (!inherits(x$DatesR, "POSIXt")) { + stop("'x$DatesR' should be of class 'POSIXt'") } - DatesR <- TabSeries$DatesR + DatesR <- x$DatesR } else { # Auto-detection of POSIXt item in Tabseries itemPOSIXt <- - which(sapply(TabSeries, function(x) { + which(sapply(x, function(x) { inherits(x, "POSIXt") }, simplify = TRUE))[1] if (is.na(itemPOSIXt)) { - stop("At least one item of argument 'TabSeries' should be of class 'POSIXt'") + stop("At least one item of argument 'x' should be of class 'POSIXt'") } warning( - "Item 'DatesR' not found in 'TabSeries' argument: the item ", - names(TabSeries)[itemPOSIXt], + "Item 'DatesR' not found in 'x' argument: the item ", + names(x)[itemPOSIXt], " has been automatically chosen" ) - DatesR <- TabSeries[[names(TabSeries)[itemPOSIXt]]] + DatesR <- x[[names(x)[itemPOSIXt]]] } # Selection of numeric items for aggregation - numericCols <- names(which(sapply(TabSeries, inherits, "numeric"))) - arrayCols <- names(which(sapply(TabSeries, inherits, "array"))) + numericCols <- names(which(sapply(x, inherits, "numeric"))) + arrayCols <- names(which(sapply(x, inherits, "array"))) numericCols <- setdiff(numericCols, arrayCols) if (!is.null(except)) { if (!inherits(except, "character")) { @@ -51,14 +47,14 @@ SeriesAggreg.list <- function(TabSeries, numericCols <- setdiff(numericCols, except) } - cols <- TabSeries[numericCols] + cols <- x[numericCols] lengthCols <- sapply(cols, length, simplify = TRUE) if (any(lengthCols != length(DatesR))) { sErr <- paste0(names(lengthCols)[lengthCols != length(DatesR)], " (", lengthCols[lengthCols != length(DatesR)], ")", collapse = ", ") warning( - "The length of the following `numeric` items in 'TabSeries' ", + "The length of the following `numeric` items in 'x' ", "is different than the length of 'DatesR (", length(DatesR), ")': they will be ignored in the aggregation: ", @@ -97,10 +93,10 @@ SeriesAggreg.list <- function(TabSeries, # Exploration of embedded lists and data.frames if (is.null(recursive) || recursive) { - listCols <- TabSeries[sapply(TabSeries, inherits, "list")] - dfCols <- TabSeries[sapply(TabSeries, inherits, "data.frame")] + listCols <- x[sapply(x, inherits, "list")] + dfCols <- x[sapply(x, inherits, "data.frame")] dfCols <- - c(dfCols, TabSeries[sapply(TabSeries, inherits, "matrix")]) + c(dfCols, x[sapply(x, inherits, "matrix")]) listCols <- listCols[setdiff(names(listCols), names(dfCols))] if (length(listCols) > 0) { # Check for predefined ConvertFun for all sub-elements @@ -153,13 +149,13 @@ SeriesAggreg.list <- function(TabSeries, } # Store elements that are not aggregated - res <- c(res, TabSeries[setdiff(names(TabSeries), names(res))]) + res <- c(res, x[setdiff(names(x), names(res))]) class(res) <- gsub( "hourly|daily|monthly|yearly", getSeriesAggregClass(Format), - class(TabSeries) + class(x) ) return(res) diff --git a/R/UtilsSeriesAggreg.R b/R/UtilsSeriesAggreg.R index de72c97487b10ba15adfb74aaf36e0e08c15a64f..247ce7df9e18b8c87d83b7290e25759ef4ed9ef9 100644 --- a/R/UtilsSeriesAggreg.R +++ b/R/UtilsSeriesAggreg.R @@ -47,7 +47,7 @@ getSeriesAggregClass <- function(Format) { Outputs = c("Prod","Rout","Exp","SnowPack","ThermalState", "Gratio","Temp","Gthreshold","Glocalmax","LayerTempMean", "T")), data.frame(ConvertFun = "sum", - Outputs = c("zzz","PotEvap","Precip","Pn","Ps","AE","Perc","PR","Q9", + Outputs = c("PotEvap","Precip","Pn","Ps","AE","Perc","PR","Q9", "Q1","Exch","AExch1","AExch2","AExch","QR","QRExp", "QD","Qsim","Pliq","Psol","PotMelt","Melt","PliqAndMelt", "LayerPrecip","LayerFracSolidPrecip", "Qmm", "Qls", "E", "P", "Qupstream")) diff --git a/man/RunModel_GR1A.Rd b/man/RunModel_GR1A.Rd index 9f52a6bc619e50bcfdae045156056ea5c89d2df7..4ebaba76d856114bb8fdbd211a391173c0139a2d 100644 --- a/man/RunModel_GR1A.Rd +++ b/man/RunModel_GR1A.Rd @@ -64,7 +64,7 @@ TabSeries <- TabSeries[TabSeries$DatesR < "2012-09-01",] TimeFormat <- "\%Y" YearFirstMonth <- 09 ConvertFun <- c("sum", "sum", "sum") -BasinObs <- SeriesAggreg(TabSeries = TabSeries, Format = TimeFormat, +BasinObs <- SeriesAggreg(TabSeries, Format = TimeFormat, YearFirstMonth = YearFirstMonth, ConvertFun = ConvertFun) ## preparation of the InputsModel object diff --git a/man/SeriesAggreg.Rd b/man/SeriesAggreg.Rd index ff8f33da4fe35d00a6d1b4305e705981c4aa0184..77105ac82c0b9f4ff343b453798a379a5e776066 100644 --- a/man/SeriesAggreg.Rd +++ b/man/SeriesAggreg.Rd @@ -31,16 +31,16 @@ Warning: on the aggregated outputs, the dates correspond to the beginning of the \usage{ -\method{SeriesAggreg}{data.frame}(TabSeries, +\method{SeriesAggreg}{data.frame}(x, Format, - ConvertFun = getAggregConvertFun(names(TabSeries)[-1]), + ConvertFun = getAggregConvertFun(names(x)[-1]), TimeFormat = NULL, NewTimeFormat = NULL, YearFirstMonth = 1, TimeLag = 0, \dots) -\method{SeriesAggreg}{list}(TabSeries, +\method{SeriesAggreg}{list}(x, Format, ConvertFun, NewTimeFormat = NULL, @@ -49,20 +49,20 @@ Warning: on the aggregated outputs, the dates correspond to the beginning of the recursive = TRUE, \dots) -\method{SeriesAggreg}{InputsModel}(TabSeries, \dots) +\method{SeriesAggreg}{InputsModel}(x, \dots) -\method{SeriesAggreg}{OutputsModel}(TabSeries, \dots) +\method{SeriesAggreg}{OutputsModel}(x, \dots) } \arguments{ -\item{TabSeries}{[InputsModel], [OutputsModel], [list] or [data.frame] containing the vector of dates (POSIXt) and the time series of numeric values} +\item{x}{[InputsModel], [OutputsModel], [list] or [data.frame] containing the vector of dates (POSIXt) and the time series of numeric values} \item{Format}{[character] output time step format (i.e. yearly times series: \code{"\%Y"}, monthly time series: \code{"\%Y\%m"}, daily time series: \code{"\%Y\%m\%d"}, monthly regimes \code{"\%m"}, daily regimes \code{"\%d"})} \item{TimeFormat}{(deprecated) [character] input time step format (i.e. \code{"hourly"}, \code{"daily"}, \code{"monthly"} or \code{"yearly"})} -\item{NewTimeFormat}{(deprecated) [character] output time step format (i.e. \code{"hourly"}, \code{"daily"}, \code{"monthly"} or \code{"yearly"}). Use the \code{TabSeries} argument instead} +\item{NewTimeFormat}{(deprecated) [character] output time step format (i.e. \code{"hourly"}, \code{"daily"}, \code{"monthly"} or \code{"yearly"}). Use the \code{x} argument instead} \item{ConvertFun}{[character] names of aggregation functions (e.g. for P[mm], T[degC], Q[mm]: \code{ConvertFun = c("sum", "mean", "sum"})) (Default: use the name of the column (See details) or "mean" for regime calculation)} @@ -95,13 +95,13 @@ data(L0123002) TabSeries <- BasinObs[, c("DatesR", "P", "E", "T", "Qmm")] ## monthly time series -NewTabSeries <- SeriesAggreg(TabSeries = TabSeries, +NewTabSeries <- SeriesAggreg(TabSeries, Format = "\%Y\%m", ConvertFun = c("sum", "sum", "mean", "sum")) str(NewTabSeries) ## monthly regimes -NewTabSeries <- SeriesAggreg(TabSeries = TabSeries, +NewTabSeries <- SeriesAggreg(TabSeries, Format = "\%m", ConvertFun = c("sum", "sum", "mean", "sum")) str(NewTabSeries) diff --git a/tests/testthat/test-SeriesAggreg.R b/tests/testthat/test-SeriesAggreg.R index 9e197d80b98e4e5986ae56094a0f62bbba3b1523..b59f920d0c88cebad30c3fce5f8eb95742e6761f 100644 --- a/tests/testthat/test-SeriesAggreg.R +++ b/tests/testthat/test-SeriesAggreg.R @@ -5,55 +5,51 @@ data(L0123002) test_that("No warning with InputsModel Cemaneige'", { ## preparation of the InputsModel object - InputsModel <- - CreateInputsModel( - FUN_MOD = RunModel_CemaNeige, - DatesR = BasinObs$DatesR, - Precip = BasinObs$P, - TempMean = BasinObs$T, - ZInputs = BasinInfo$HypsoData[51], - HypsoData = BasinInfo$HypsoData, - NLayers = 5 - ) + InputsModel <- CreateInputsModel( + FUN_MOD = RunModel_CemaNeige, + DatesR = BasinObs$DatesR, + Precip = BasinObs$P, + TempMean = BasinObs$T, + ZInputs = BasinInfo$HypsoData[51], + HypsoData = BasinInfo$HypsoData, + NLayers = 5 + ) # Expect no warning: https://stackoverflow.com/a/33638939/5300212 expect_warning(SeriesAggreg(InputsModel, "%m"), regexp = NA) }) test_that("Warning: deprecated 'TimeFormat' argument", { - InputsModel <- - CreateInputsModel( - FUN_MOD = RunModel_GR4J, - DatesR = BasinObs$DatesR, - Precip = BasinObs$P, - PotEvap = BasinObs$E - ) + InputsModel <- CreateInputsModel( + FUN_MOD = RunModel_GR4J, + DatesR = BasinObs$DatesR, + Precip = BasinObs$P, + PotEvap = BasinObs$E + ) expect_warning(SeriesAggreg(InputsModel, Format = "%Y%m", TimeFormat = "daily"), regexp = "deprecated 'TimeFormat' argument") }) test_that("Warning: deprecated 'NewTimeFormat' argument: please use 'Format' instead", { - InputsModel <- - CreateInputsModel( - FUN_MOD = RunModel_GR4J, - DatesR = BasinObs$DatesR, - Precip = BasinObs$P, - PotEvap = BasinObs$E - ) + InputsModel <- CreateInputsModel( + FUN_MOD = RunModel_GR4J, + DatesR = BasinObs$DatesR, + Precip = BasinObs$P, + PotEvap = BasinObs$E + ) expect_warning(SeriesAggreg(InputsModel, NewTimeFormat = "monthly"), regexp = "deprecated 'NewTimeFormat' argument: please use 'Format' instead") }) test_that("Warning: deprecated 'NewTimeFormat' argument: 'Format' argument is used instead", { - InputsModel <- - CreateInputsModel( - FUN_MOD = RunModel_GR4J, - DatesR = BasinObs$DatesR, - Precip = BasinObs$P, - PotEvap = BasinObs$E - ) + InputsModel <- CreateInputsModel( + FUN_MOD = RunModel_GR4J, + DatesR = BasinObs$DatesR, + Precip = BasinObs$P, + PotEvap = BasinObs$E + ) expect_warning(SeriesAggreg(InputsModel, Format = "%Y%m", NewTimeFormat = "monthly"), regexp = "deprecated 'NewTimeFormat' argument: 'Format' argument is used instead") }) @@ -85,13 +81,12 @@ test_that("No DatesR should warning", { }) test_that("Check SeriesAggreg.list 'DatesR' argument", { - InputsModel <- - CreateInputsModel( - FUN_MOD = RunModel_GR4J, - DatesR = BasinObs$DatesR, - Precip = BasinObs$P, - PotEvap = BasinObs$E - ) + InputsModel <- CreateInputsModel( + FUN_MOD = RunModel_GR4J, + DatesR = BasinObs$DatesR, + Precip = BasinObs$P, + PotEvap = BasinObs$E + ) DatesR <- InputsModel$DatesR # No InputsModel$DatesR InputsModel$DatesR <- NULL @@ -186,7 +181,8 @@ test_that("Check data.frame handling in SeriesAggreg.list", { regexp = NA) I2 <- SeriesAggreg(InputsModelDown1, "%Y%m") expect_equal(length(I2$DatesR), nrow(I2$Qupstream)) - InputsModelDown1$Qupstream <- InputsModelDown1$Qupstream[-1, , drop=FALSE] # https://stackoverflow.com/a/7352287/5300212 + InputsModelDown1$Qupstream <- + InputsModelDown1$Qupstream[-1, , drop = FALSE] # https://stackoverflow.com/a/7352287/5300212 expect_warning(SeriesAggreg(InputsModelDown1, "%Y%m"), - regexp = "it will be ignored in the aggregation") + regexp = "it will be ignored in the aggregation") })