@@ -215,7 +215,7 @@ tsEvaTransformSeriesToStationaryTrendOnly_ciPercentile <- function(timeStamps,
215215# ' @param series A vector of the time series data.
216216# ' @param timeWindow The size of the time window used for detrending.
217217# ' @param TrendTh The threshold for fitting the trend on the means above a
218- # ' given quantile. Default is 0.5.
218+ # ' given quantile. If "NA", default to 0.5.
219219# '
220220# ' @return A list containing the following components:
221221# ' \describe{
@@ -263,53 +263,160 @@ tsEvaTransformSeriesToStationaryPeakTrend <- function(timeStamps, series, timeWi
263263 }
264264 message(paste0(" trend threshold= " , TrendTh ))
265265 qd <- quantile(series , TrendTh , na.rm = T )
266- serieb <- series
267- serieb [which(serieb < qd )] <- NA
266+ series_above_threshold <- series
267+ series_above_threshold [which(series_above_threshold < threshold )] <- NA
268268
269269
270- rs <- tsEvaDetrendTimeSeries(timeStamps , serieb , timeWindow )
270+ detrend_result <- tsEvaDetrendTimeSeries(timeStamps , series_above_threshold , timeWindow )
271+
272+ # Detrend the series
273+ detrended_series <- series - detrend_result @ trendSeries
274+ detrended_series_above_threshold <- series_above_threshold - detrend_result @ trendSeries
275+
276+ # Calculate running variance and standard deviation
277+ n_run_mean <- detrend_result @ nRunMn
278+ variance_series <- tsEvaNanRunningVariance(detrended_series_above_threshold , n_run_mean )
279+ variance_series <- tsEvaNanRunningMean(variance_series , ceiling(n_run_mean / 2 ))
280+ std_dev_series <- sqrt(variance_series )
281+ avg_std_dev <- mean(std_dev_series , na.rm = TRUE )
282+ S <- 2
283+
284+ # Calculate error on standard deviation
285+ N <- timeWindow * 4
286+ std_dev_error <- avg_std_dev * (2 * S ^ 2 / N ^ 3 )^ (1 / 4 )
287+
288+ # Compute running statistics of the stationary series
289+ stationary_series <- detrended_series / std_dev_series
290+ stationary_series_no_na <- na.omit(stationary_series )
291+
292+ running_moments <- tsEvaNanRunningStatistics(stationary_series_no_na , n_run_mean )
293+ stat_ser_3_mom <- tsEvaNanRunningMean(running_moments $ rn3mom , ceiling(n_run_mean ))
294+ stat_ser_4_mom <- tsEvaNanRunningMean(running_moments $ rn4mom , ceiling(n_run_mean ))
295+
296+ # Calculate error on the trend
297+ trend_error <- avg_std_dev / sqrt(N )
271298
272- # adding the threshold to avoid values on the zero
299+ # Store the results in a list
300+ transformed_data <- list (
301+ runningStatsMulteplicity = n_run_mean ,
302+ stationarySeries = stationary_series ,
303+ trendSeries = detrend_result @ trendSeries ,
304+ trendSeriesNonSeasonal = NULL ,
305+ trendError = trend_error ,
306+ stdDevSeries = std_dev_series ,
307+ stdDevSeriesNonSeasonal = NULL ,
308+ stdDevError = std_dev_error * rep(1 , length(std_dev_series )),
309+ timeStamps = timeStamps ,
310+ nonStatSeries = series ,
311+ statSer3Mom = stat_ser_3_mom ,
312+ statSer4Mom = stat_ser_4_mom
313+ )
314+
315+ return (transformed_data )
316+ }
317+
318+ # ' tsEvaTransformSeriesToStationaryMMXTrend
319+ # '
320+ # ' \code{tsEvaTransformSeriesToStationaryMMXTrend}
321+ # ' transforms a time series to a stationary one by focusing on the monthly maximum values.
322+ # ' The trend and slowly varying amplitude are computed on the monthly maximum values.
323+ # '
324+ # ' @param timeStamps A vector of time stamps corresponding to the observations in the series.
325+ # ' @param series A vector of the time series data.
326+ # ' @param timeWindow The size of the time window used for detrending.
327+ # '
328+ # ' @return A list containing the following components:
329+ # ' \describe{
330+ # ' \item{\code{runningStatsMulteplicity}}{The multiplicity of running statistics.}
331+ # ' \item{\code{stationarySeries}}{The stationary series after removing the trend.}
332+ # ' \item{\code{trendSeries}}{The trend component of the series.}
333+ # ' \item{\code{trendSeriesNonSeasonal}}{NULL (not used).}
334+ # ' \item{\code{trendError}}{The error on the trend component.}
335+ # ' \item{\code{stdDevSeries}}{The standard deviation series.}
336+ # ' \item{\code{stdDevSeriesNonSeasonal}}{NULL (not used).}
337+ # ' \item{\code{stdDevError}}{The error on the standard deviation series.}
338+ # ' \item{\code{timeStamps}}{The time stamps.}
339+ # ' \item{\code{nonStatSeries}}{The original non-stationary series.}
340+ # ' \item{\code{statSer3Mom}}{The running mean of the third moment of the stationary series.}
341+ # ' \item{\code{statSer4Mom}}{The running mean of the fourth moment of the stationary series.}
342+ # ' }
343+ # '
344+ # ' @import stats
345+ # ' @importFrom dplyr mutate group_by summarise
346+ # ' @importFrom lubridate floor_date
347+ # ' @examples
348+ # ' timeAndSeries <- ArdecheStMartin
349+ # ' timeStamps <- ArdecheStMartin[,1]
350+ # ' series <- ArdecheStMartin[,2]
351+ # ' # select only the 5 latest years
352+ # ' yrs <- as.integer(format(timeStamps, "%Y"))
353+ # ' tokeep <- which(yrs >= 2015)
354+ # ' timeStamps <- timeStamps[tokeep]
355+ # ' series <- series[tokeep]
356+ # ' timeWindow <- 365 # 1 year
357+ # ' result <- tsEvaTransformSeriesToStationaryMMXTrend(timeStamps, series, timeWindow)
358+ # ' plot(result$trendSeries)
359+ # '
360+ # ' @seealso [tsEvaDetrendTimeSeries()], [tsEvaNanRunningVariance()],
361+ # ' [tsEvaNanRunningMean()], [tsEvaNanRunningStatistics()], [mutate()], [group_by()],
362+ # ' [summarise()], [floor_date()]
363+ # ' @export
364+ tsEvaTransformSeriesToStationaryMMXTrend <- function (timeStamps , series , timeWindow ) {
365+ # Check if timeStamps and series are of the same length
366+ if (length(timeStamps ) != length(series )) {
367+ stop(" timeStamps and series must be of the same length." )
368+ }
369+
370+ # Check if timeWindow is a positive integer
371+ if (! is.numeric(timeWindow ) || timeWindow < = 0 ) {
372+ stop(" timeWindow must be a positive integer." )
373+ }
374+
375+ # Create a data frame with timeStamps and series
376+ tserie <- data.frame (timeStamps , series )
377+
378+ # Calculate monthly maximum values
379+ monthly_max <- tserie %> %
380+ mutate(month = floor_date(timeStamps , " month" )) %> %
381+ group_by(month ) %> %
382+ summarise(max_value = max(series , na.rm = TRUE ))
383+
384+ # Create a series with only the monthly maximum values
385+ serieb <- series
386+ tm <- na.omit(match(as.Date(as.character(monthly_max $ month )), as.Date(timeStamps )))
387+ serieb [- tm ] <- NA
388+
389+ # Detrend the series based on monthly maximum values
390+ rs <- tsEvaDetrendTimeSeries(timeStamps , serieb , timeWindow )
273391 detrendSeries <- series - rs @ trendSeries
274392 detrendSerie1 <- serieb - rs @ trendSeries
275- qd2 <- min(detrendSerie1 , na.rm = T )
276- nRunMn <- rs @ nRunMn
277393
394+ # Calculate running variance and standard deviation
395+ nRunMn <- rs @ nRunMn
278396 varianceSeries <- tsEvaNanRunningVariance(detrendSerie1 , nRunMn )
279- # further smoothing
280397 varianceSeries <- tsEvaNanRunningMean(varianceSeries , ceiling(nRunMn / 2 ))
281-
282- stdDevSeries1 <- varianceSeries ^ .5
398+ stdDevSeries1 <- varianceSeries ^ 0.5
283399 stdDevSeries <- stdDevSeries1
284- avgStdDev <- mean(stdDevSeries )
400+ avgStdDev <- mean(stdDevSeries , na.rm = TRUE )
285401 S <- 2
286402
287- # N is the size of each sample used to compute the average
288- # Counts the real amount of timstep, need to specify original temporal resolution
403+ # Calculate error on standard deviation
289404 N <- timeWindow * 4
290- # computation of the error on the standard deviation explained in
291- # Mentaschi et al 2016
292405 stdDevError <- avgStdDev * (2 * S ^ 2 / N ^ 3 )^ (1 / 4 )
293406
294407 # Compute running statistics of the stationary series
295408 statSeries <- detrendSeries / stdDevSeries
409+ statSeries_no_na <- na.omit(statSeries )
296410
297- xtremS <- statSeries
298- xtremS <- na.omit(xtremS )
299- allS <- na.omit(serieb )
300-
301- statSer3Mom <- tsEvaNanRunningStatistics(statSeries , nRunMn )$ rn3mom
302- statSer4Mom <- tsEvaNanRunningStatistics(statSeries , nRunMn )$ rn4mom
303- statSer3Mom <- tsEvaNanRunningMean(statSer3Mom , ceiling(nRunMn ))
304- statSer4Mom <- tsEvaNanRunningMean(statSer4Mom , ceiling(nRunMn ))
305-
411+ running_moments <- tsEvaNanRunningStatistics(statSeries_no_na , nRunMn )
412+ statSer3Mom <- tsEvaNanRunningMean(running_moments $ rn3mom , ceiling(nRunMn ))
413+ statSer4Mom <- tsEvaNanRunningMean(running_moments $ rn4mom , ceiling(nRunMn ))
306414
307- # the error on the trend is computed as the error on the average:
308- # error(average) = stdDev/sqrt(N)
309- trendError <- mean(stdDevSeries ) / N ^ .5
415+ # Calculate error on the trend
416+ trendError <- avgStdDev / sqrt(N )
310417
311418 # Store the results in a list
312- trasfData <- list (
419+ transformed_data <- list (
313420 runningStatsMulteplicity = nRunMn ,
314421 stationarySeries = statSeries ,
315422 trendSeries = rs @ trendSeries ,
@@ -324,7 +431,7 @@ tsEvaTransformSeriesToStationaryPeakTrend <- function(timeStamps, series, timeWi
324431 statSer4Mom = statSer4Mom
325432 )
326433
327- return (trasfData )
434+ return (transformed_data )
328435}
329436
330437
0 commit comments