Nothing
# File subhourly2nminutes.R
# Part of the hydroTSM R package, https://github.com/hzambran/hydroTSM ;
# https://CRAN.R-project.org/package=hydroTSM
# Copyright 2022-2023 Mauricio Zambrano-Bigiarini
# Distributed under GPL 2 or later
################################################################################
# subhourly2nminutes #
################################################################################
# This function transform a SUB-HOURLY time series into a n-minutes one
# 'x' : sub-hourly values that will be agreggated into n-minutes ones.
# class(x) must be 'zoo'
# 'FUN' : Function that have to be applied for transforming from sub-hourly into
# n-minutes time step. E.g., for precipitation FUN MUST be "sum"
# For temperature and flow time series, FUN MUST be "mean"
# 'na.rm': Logical. Should missing values be removed?
# TRUE : the monthly and annual values are computed considering only those values different from NA
# FALSE: if there is AT LEAST one NA within a year, the monthly and annual values are NA
subhourly2nminutes <-function(x, ...) UseMethod("subhourly2nminutes")
################################################################################
# Author : Mauricio Zambrano-Bigiarini #
################################################################################
# Started: 15-Oct-2022 #
# Updates: 29-Ago-2023 #
################################################################################
subhourly2nminutes.default <- function(x, nminutes, FUN, na.rm=TRUE,
from=start(x), to=end(x), ...) {
# Checking that 'x' is a zoo object
if ( !is.zoo(x) ) stop("Invalid argument: 'class(x)' must be 'zoo'")
subhourly2nminutes.zoo(x=x, nminutes=nminutes, FUN=FUN, na.rm=na.rm, ...)
} # 'subhourly2nminutes.default' end
################################################################################
# Author : Mauricio Zambrano-Bigiarini #
################################################################################
# Started: 15-Oct-2022 #
# Updates: 25-Oct-2022 #
# 29-Ago-2023 ; 11-Oct-2023 #
################################################################################
subhourly2nminutes.zoo <- function(x, nminutes, FUN, na.rm=TRUE,
from=start(x), to=end(x), ...) {
# testing the existence of 'na.rm' argument
#args <- list(...)
#exist <- "na.rm" %in% names(args)
#exist
# Checking that the user provided a valid class for 'x'
if ( !is.zoo(x) ) stop("Invalid argument: 'class(x)' must be 'zoo' !!")
# Checking that the user provided a sub-hourly 'x' object
if ( !(sfreq(x) == "minute" ) ) stop("Invalid argument: 'x' is not a sub-hourly ts !!")
# Checking the user provide a valid value for 'FUN'
if (missing(FUN))
stop("Missing argument: 'FUN' must contain a valid function for aggregating the sub-daily values")
# Getting the amount of minutes between each 'x' value, which might be irregularly spaced
x.nmin <- diff(time(x))
x.nmin.units <- units(x.nmin)
x.nmin <- min(x.nmin)
if (x.nmin.units == "secs") {
x.nmin <- as.numeric(x.nmin/60)
} else x.nmin <- as.numeric(x.nmin)
# Checking that the amount of minutes used for aggregation ('nminutes') is provided and larger than 'x.nmin'
if (missing(nminutes)) {
stop("Missing argument: 'nminutes' must be provided !")
} else if ( nminutes <= x.nmin)
stop("Invalid argument: 'nminutes' must be larger than the time frequency of 'x' !!")
lstart <- start(x)
if ( !missing(from) ) {
if (from < lstart) {
x <- izoo2rzoo(x, from=from)
} else x <- window(x, start=from)
} # IF end
lend <- end(x)
if ( !missing(to) ) {
if (to > lend) {
x <- izoo2rzoo(x, to=to)
} else x <- window(x, end=to)
} # IF end
# Getting the time zone of 'x'
ltz <- format(time(x), "%Z")[1]
lstart <- start(x)
lend <- end(x)
temp <- seq( lstart, lend, by=paste0(nminutes, " min") )
# temporal aggregation from 'x.nmin' minutes to 'nminutes' minutes
h <- aggregate(x, by= function(tt) cut(tt, breaks=temp), FUN=FUN, na.rm= na.rm, ...)
# I don't know why, but the time attribute of the resulting object 'h' is 'factor' (not PSOIXct),
# and the '00:00:00' is removed from time corresponding to the full hour
# (e.g., '2021-01-01 00:00:00' becomes '2021-01-01')
# Transforming 'time(x)' from factor into a POSIXct object
lt <- as.character(time(h))
index <- which(substr(lt, 12, 19) == "")
lt[index] <- paste(lt[index], "00:00:00")
h <- zoo(coredata(h), as.POSIXct(lt, format="%Y-%m-%d %H:%M", tz=ltz ))
# Replacing the NaNs by 'NA.
# mean(NA:NA, na.rm=TRUE) == NaN
nan.index <- which(is.nan(h))
if ( length(nan.index) > 0 ) h[nan.index] <- NA
# Replacing all the Inf and -Inf by NA's
# min(NA:NA, na.rm=TRUE) == Inf ; max(NA:NA, na.rm=TRUE) == -Inf
inf.index <- which(is.infinite(h))
if ( length(inf.index) > 0 ) h[inf.index] <- NA
return(h)
} # 'subhourly2nminutes.zoo' end
################################################################################
# Author : Mauricio Zambrano-Bigiarini #
################################################################################
# Started: 15-Oct-2022 #
# Updates: 29-Ago-2023 #
################################################################################
# 'dates' : "numeric", "factor", "Date" indicating how to obtain the
# dates for correponding to the 'sname' station
# If 'dates' is a number, it indicates the index of the column in
# 'x' that stores the dates
# If 'dates' is a factor, it have to be converted into 'Date' class,
# using the date format specified by 'date.fmt'
# If 'dates' is already of Date class, the following line verifies that
# the number of days in 'dates' be equal to the number of element in the
# time series corresponding to the 'st.name' station
# 'date.fmt': format in which the dates are stored in 'dates'.
# ONLY required when class(dates)=="factor" or "numeric"
# 'out.fmt' : character, for selecting if the result will be 'numeric' or 'zoo'. Valid values are: c('numeric', 'zoo')
# 'verbose' : logical; if TRUE, progress messages are printed
subhourly2nminutes.data.frame <- function(x, nminutes, FUN, na.rm=TRUE,
from=start(x), to=end(x),
dates=1, date.fmt="%Y-%m-%d %H:%M:%S",
out.fmt="zoo", verbose=TRUE,...) {
# Checking that the user provide a valid value for 'FUN'
if (missing(FUN))
stop("Missing argument value: 'FUN' must contain a valid function for aggregating the values !!")
# Checking that the user provided a valid argument for 'out.fmt'
if (is.na(match( out.fmt, c("numeric", "zoo") ) ) )
stop("Invalid argument: 'out.fmt' must be in c('numeric', 'zoo')")
# Checking that the user provided a valid argument for 'dates'
if (missing(dates)) {
stop("Missing argument: 'dates' must be provided")
} else
# Checking that the user provided a valid argument for 'dates'
if (FALSE && (class(dates) %in% c("numeric", "factor", "POSIXct", "POSIXt")) )
stop("Invalid argument: 'dates' must be of class 'numeric', 'factor', 'POSIXct', 'POSIXt'")
# If 'dates' is a number, it indicates the index of the column of 'x' that stores the dates
# The column with dates is then substracted form 'x' for easing the further computations
if ( TRUE && ( inherits(dates, "numeric") ) ) {
tmp <- dates
dates <- as.POSIXct(x[, dates], format= date.fmt)
x <- x[-tmp]
} # IF end
# If 'dates' is a factor, it have to be converted into 'Date' class,
# using the date format specified by 'date.fmt'
if ( TRUE && ( inherits(dates, "factor") ) ) dates <- as.POSIXct(dates, format= date.fmt)
# If 'dates' is already of Date class, the following line verifies that
# the number of days in 'dates' be equal to the number of element in the
# time series corresponding to the 'st.name' station
if ( (TRUE && (class(dates) %in% c("POSIXct", "POSIXt")) ) & (length(dates) != nrow(x) ) )
stop("Invalid argument: 'length(dates)' must be equal to 'nrow(x)'")
# Transforming 'x' into a zoo object
x <- zoo::zoo(x, dates)
##############################################################################
z <- subhourly2nminutes.zoo(x=x, nminutes=nminutes, FUN=FUN, na.rm=na.rm,
from=from, to=to, ...)
if (out.fmt == "numeric") {
snames <- colnames(z)
dates.lab <- as.character(time(z))
z <- coredata(z)
colnames(z) <- snames
rownames(z) <- dates.lab
} # IF end
return( z )
} #'subhourly2nminutes.data.frame' END
################################################################################
# Author : Mauricio Zambrano-Bigiarini #
################################################################################
# Started: 15-Oct-2022 #
# Updates: 29-Ago-2023 #
################################################################################
subhourly2nminutes.matrix <- function(x, nminutes, FUN, na.rm=TRUE,
from=start(x), to=end(x),
dates=1, date.fmt="%Y-%m-%d %H:%M:%S",
out.fmt="zoo",
verbose=TRUE,...) {
x <- as.data.frame(x)
#NextMethod("daily2annual") # I don't know why is redirecting to 'daily2monthly.default' instead of 'daily2monthly.data.frame'....
subhourly2nminutes.data.frame(x=x, nminutes=nminutes, FUN=FUN, na.rm=na.rm,
from=from, to=to, dates=dates, date.fmt=date.fmt,
out.fmt=out.fmt, verbose=verbose,...)
} # 'subhourly2nminutes.matrix ' 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.