#library(devtools) #document() #load_all(as.package("../../onlineforecast")) #?rls_update #' Calculates the RLS update of the model coefficients with the provived data. #' #' See vignette ??ref(recursive updating, not yet finished) on how to use the function. #' #' @title Updates the model fits #' @param model A model object #' @param datatr a data.list with transformed data (from model$transform_data(D)) #' @param y A vector of the model output for the corresponding time steps in \code{datatr} #' @param runcpp Optional, default = TRUE. If TRUE, a c++ implementation of the update is run, otherwise a slower R implementation is used. #' @return #' #' Returns a named list for each horizon (\code{model$kseq}) containing the variables needed for the RLS fit (for each horizon, which is saved in model$Lfits): #' #' It will update variables in the forecast model object. #' #' @seealso #' See \code{\link{rls_predict}}. #' #' @examples #' #' # See rls_predict examples #' #' @export rls_update <- function(model, datatr = NA, y = NA, runcpp=TRUE) { # Take the inputs data and bind with the kept inputs data in the fit # # The data must be kept for later updating, done below # The last part of the input data is needed for next update # Find the number of parameters for the regression np <- length(datatr) # Keep only the last kmax rows for next time kmax <- max(as.integer(gsub("k", "", nams(datatr[[1]])))) # Check if data was kept kept_input_data <- !is.na(model$datatr[1]) # if (kept_input_data) { # Find the start index for iterating later (the index to start updating from) # How many points are kept plus one istart <- nrow(model$datatr[[1]]) + 1 # Bind together new and kept data for (i in 1:length(datatr)) { # Bind them datatr[[i]] <- rbind(model$datatr[[i]], datatr[[i]]) # Keep only the last kmax rows for next time # Done below: model$datatr[[i]] <- datatr[[i]][(n+1):(kmax+n), ] } # Also for y to sync with X y <- c(rep(NA,istart-1), y) } else { # Set later when nothing is kept (it must be set to k+1) istart <- NA } # The number of points n <- length(y) # Parameters for rls lambda <- model$regprm$lambda if(runcpp){ L <- lapply(model$Lfits, function(fit) { # Take the needed values from the fit k <- fit$k theta <- fit$theta # The non cpp keeps R, see below if(is.null(fit$P)){ P <- solve(fit$R) }else{ P <- fit$P } # Form the regressor matrix, don't lag it X <- as.matrix(as.data.frame(subset(datatr, kseq=k))) # When nothing was kept if(!kept_input_data){ istart <- k + 1 } val <- rls_update_cpp(y, X, theta, P, lambda, k, n, np, istart, kmax) # Give names to the matrices (maybe faster if done in cpp function, see in the end) colnames(val$fit$P) <- names(datatr) colnames(val$result$Theta) <- names(datatr) # Give the result return(val) }) }else{ # Fit the model for each k L <- lapply(model$Lfits, function(fit) { # Take the needed values from the fit k <- fit$k theta <- fit$theta # The cpp keeps P if (is.null(fit$R)) { R <- solve(fit$P) } else { R <- fit$R } # Form the regressor matrix, don't lag it X <- as.data.frame(subset(datatr, kseq=k)) # Prepare for keeping for the parameter estimates Theta <- matrix(as.numeric(NA), nrow = n, ncol = np) # Make vector for predictions k steps ahead yhat <- rep(NA,length(y)) # If input data was kept (i.e. it is not a fresh update), NAs was added above in X and y, so insert the kept yhat if(kept_input_data){ yhat[1:length(fit$yhat)] <- fit$yhat} # When nothing was kept if(!kept_input_data){ istart <- k + 1 } # Iterate through for (i in istart:n) { # Take the forecast k steps back to match it with y[i] x <- t(as.matrix(X[i-k, ])) if(!any(is.na(x)) & !is.na(y[i])){ # Update R <- lambda * R + x %*% t(x) theta <- theta + solve(R, x) %*% (y[i] - t(x) %*% theta) Theta[i, ] <- t(theta) } # Make a prediction yhat[i] <- as.matrix(X[i, ]) %*% theta } # # Give names to the matrices colnames(R) <- names(datatr) colnames(Theta) <- names(datatr) # Return the fit and result return(list(fit=list(k=k, theta=theta, R=R, yhat=yhat[(n-kmax+1):n]), result=list(yhat=yhat, Theta=Theta))) }) } # # Keep the last part of the transformed data for later model$datatr <- subset(datatr, (n-kmax+1):n) # Store the values of y if the model has AR term if(!is.na(model$maxlagAR)){ # Was data kept? if(kept_input_data){ # Yes, so put together with the kept tmpy <- c(model$yAR, y[istart:n]) }else{ # No, then just take from y tmpy <- y } # In case too few new values, then fill with NAs if((model$maxlagAR+1) > length(tmpy)){ tmpy <- c(rep(NA,(model$maxlagAR+1)-length(tmpy)), tmpy) } # Keep the needed model$yAR <- tmpy[(length(tmpy)-model$maxlagAR):length(tmpy)] } # # Keep the fit model$Lfits <- getse(L, "fit") # Return Theta in a list for each k invisible(getse(L, "result")) }