@@ -100,13 +100,13 @@ ARml <- function(y,
100100 pre_process = NULL ,
101101 cv = TRUE ,
102102 cv_horizon = 4 ,
103- initial_window = length( y ) - max_lag - cv_horizon * 2 ,
103+ initial_window = NULL ,
104104 fixed_window = FALSE ,
105105 verbose = TRUE ,
106106 seasonal = TRUE ,
107107 K = frequency(y ) / 2 ,
108108 tune_grid = NULL ,
109- lambda = " auto " ,
109+ lambda = NULL ,
110110 BoxCox_method = c(" guerrero" , " loglik" ),
111111 BoxCox_lower = - 1 ,
112112 BoxCox_upper = 2 ,
@@ -118,27 +118,52 @@ ARml <- function(y,
118118 if (" ts" %notin % class(y )) {
119119 stop(" y must be a univariate time series" )
120120 }
121-
121+ freq <- stats :: frequency( y )
122122 length_y <- length(y )
123123
124- freq <- stats :: frequency(y )
124+ if (c(length_y - freq - round(freq / 4 )) < max_lag ) {
125+ if (length_y > 3 ){
126+ max_lag <- length_y + 3 - length_y
127+ } else {
128+ max_lag <- 1
129+ }
130+ if (max_lag > = length_y - max_lag - 2 ){
131+ max_lag <- 1
132+ }
133+
134+ warning(paste(" Input data is too short. setting max_lag = " , max_lag ))
135+ }
125136
126- if (length_y < freq ) {
137+ if (length_y < 3 ) {
127138 stop(" Not enough data to fit a model" )
128139 }
140+ constant_data <- is.constant(na.interp(y ))
141+ if (constant_data ) {
142+ warning(" Constant data, setting max_lag = 1, seasonal = FALSE, lambda = NULL,
143+ pre_process = NULL" )
144+ pre_process <- NULL
145+ lambda <- NULL
146+ max_lag <- 1
147+ }
148+
149+ if (! is.null(xreg )) {
150+ constant_xreg <- any(apply(as.matrix(xreg ), 2 ,
151+ function (x ) {
152+ is.constant(na.interp(x ))
153+ }
154+ )
155+ )
156+ if (constant_xreg ) {
157+ warning(" Constant xreg column, setting pre_process=NULL" )
158+ pre_process <- NULL
159+ }
160+ }
129161
130162 if (max_lag < = 0 ) {
131163 warning(" max_lag increased to 1. max_lag must be max_lag >= 1" )
132164 max_lag <- 1
133165 }
134166
135- if (c(length_y - freq - round(freq / 4 )) < max_lag ) {
136- warning(paste(
137- " Input data is too short. Reducing max_lags to " ,
138- round(length_y - freq - round(freq / 4 ))
139- ))
140- max_lag <- round(length_y - freq - round(freq / 4 ))
141- }
142167
143168 if (max_lag != round(max_lag )) {
144169 max_lag <- round(max_lag )
@@ -151,14 +176,6 @@ ARml <- function(y,
151176 }
152177 }
153178
154- constant_y <- forecast :: is.constant(forecast :: na.interp(y ))
155-
156- if (constant_y ) {
157- warning(" Constant data, setting max_lag = 1, lambda = NULL" )
158- lambda <- NULL
159- max_lag = 1
160- }
161-
162179 if (! is.null(xreg ))
163180 {
164181 ncolxreg <- ncol(xreg )
@@ -185,7 +202,11 @@ ARml <- function(y,
185202 start = time(modified_y )[max_lag + 1 ],
186203 frequency = freq )
187204
188- if (seasonal == TRUE | freq > 1 )
205+ if (length_y - max_lag < freq + 1 ) {
206+ seasonal <- FALSE
207+ }
208+
209+ if (seasonal == TRUE & freq > 1 )
189210 {
190211 if (K == freq / 2 ) {
191212 ncolx <- max_lag + K * 2 - 1
@@ -235,6 +256,22 @@ ARml <- function(y,
235256 }
236257 }
237258
259+ initial_window_setted <- FALSE
260+ if (is.null(initial_window )){
261+ initial_window <- length_y - max_lag - cv_horizon * 2
262+ message(" initial_window = NULL. Setting initial_window = " , initial_window )
263+ initial_window_setted <- TRUE
264+ }
265+ if (initial_window < 1 | initial_window > = nrow(x )){
266+ initial_window <- length_y - max_lag - 1
267+ cv_horizon <- 1
268+ if (initial_window_setted ){
269+ warning(" Resetting initial_window = " , initial_window , " cv_horizon = 1" )
270+ } else {
271+ warning(" Setting initial_window = " , initial_window , " cv_horizon = 1" )
272+ }
273+ }
274+
238275 model <- caret :: train(
239276 x = x ,
240277 y = as.numeric(modified_y_2 ),
@@ -303,134 +340,3 @@ ARml <- function(y,
303340 class(output ) <- " ARml"
304341 return (output )
305342}
306-
307-
308- # ' @title Forecasting an ARml object
309- # '
310- # ' @param object A list class of ARml
311- # ' @param h forecast horizon
312- # ' @param xreg Optionally, a numerical vector or matrix of future external
313- # ' regressors
314- # ' @param level Confidence level for prediction intervals.
315- # ' @param PI If TRUE, prediction intervals are produced, otherwise only point
316- # ' forecasts are calculated. If PI is FALSE, then level, fan, bootstrap and
317- # ' npaths are all ignored.
318- # ' @param num_bs Number of bootstrapped versions to generate.
319- # ' @param ... Other arguments pased to forecast::forecast()
320- # ' @return A list class of forecast containing the following elemets
321- # ' * x : The input time series
322- # ' * method : The name of the forecasting method as a character string
323- # ' * mean : Point forecasts as a time series
324- # ' * lower : Lower limits for prediction intervals
325- # ' * upper : Upper limits for prediction intervals
326- # ' * level : The confidence values associated with the prediction intervals
327- # ' * model : A list containing information about the fitted model
328- # ' * newxreg : A matrix containing regressors
329- # ' @author Resul Akay
330- # '
331- # ' @examples
332- # '
333- # 'library(caretForecast)
334- # '
335- # 'train_data <- window(AirPassengers, end = c(1959, 12))
336- # '
337- # 'test <- window(AirPassengers, start = c(1960, 1))
338- # '
339- # 'ARml(train_data, caret_method = "lm", max_lag = 12) -> fit
340- # '
341- # 'forecast(fit, h = length(test), level = c(80,95), PI = TRUE) -> fc
342- # '
343- # 'autoplot(fc)+ autolayer(test)
344- # '
345- # 'accuracy(fc, test)
346- # '
347- # ' @export
348- forecast.ARml <- function (object ,
349- h = frequency(object $ y ),
350- xreg = NULL ,
351- level = c(80 , 95 ),
352- PI = FALSE ,
353- num_bs = 1000 ,
354- ... ) {
355- if (! is.null(object $ xreg_fit )) {
356- ncolxreg <- ncol(object $ xreg_fit )
357- }
358-
359- if (is.null(xreg )) {
360- if (! is.null(object $ xreg_fit )) {
361- stop(" No regressors provided" )
362- }
363- }
364-
365- if (! is.null(xreg )) {
366- if (is.null(object $ xreg_fit )) {
367- stop(" No regressors provided to fitted model" )
368- }
369-
370- if (ncol(xreg ) != ncolxreg ) {
371- stop(" Number of regressors does not match to fitted model" )
372- }
373-
374- h <- nrow(xreg )
375- newxreg1 <- xreg
376- }
377-
378- if (is.null(h )) {
379- h <- ifelse(frequency(object $ y ) > 1 , 2 * frequency(object $ y ), 10 )
380- }
381-
382- if (is.null(xreg )) {
383- newxreg1 <- NULL
384- }
385-
386- if (PI ) {
387- if (is.null(level )) {
388- warning(" level was not provided. Prediction intervals will not be returned" )
389- PI <- FALSE
390- }
391- }
392-
393- lambda <- object $ lambda
394- BoxCox_biasadj <- object $ BoxCox_biasadj
395- BoxCox_fvar <- object $ BoxCox_fvar
396-
397- fc_x <- forecast_loop(object = object , xreg = newxreg1 , h = h )
398- x <- fc_x $ x
399- y <- fc_x $ y
400-
401- if (! is.null(lambda )) {
402- y <- forecast :: InvBoxCox(y ,
403- lambda = lambda ,
404- biasadj = BoxCox_biasadj ,
405- fvar = BoxCox_fvar )
406- }
407-
408- if (PI ) {
409- bs_pi <- pi (
410- y = object $ y ,
411- fc = y ,
412- num = num_bs ,
413- block_size = NULL ,
414- level = level
415- )
416- lower <- bs_pi [[" lower" ]]
417- upper <- bs_pi [[" upper" ]]
418- } else {
419- lower <- NULL
420- upper <- NULL
421- }
422-
423- output <- list (
424- x = object $ y ,
425- mean = y ,
426- lower = lower ,
427- upper = upper ,
428- fitted = object $ fitted ,
429- level = level ,
430- newxreg = x ,
431- method = object $ method ,
432- model = object $ model
433- )
434- class(output ) <- c(" forecast" , " forecastARml" )
435- return (output )
436- }
0 commit comments