PdV
PdV

Reputation: 63

problems with scope; R cannot find an object in the environment of a function

My objective is to fit models and produce forecasts each time just varying the y and x variables. This will make my code much more concise.

When I try to forecast on the test time series R throws an error: Error in eval(expr, envir, enclos) : object 'train' not found But train was produced inside the local environment of the function If I move train to the global environment, there is no error

What do I need to do so all statements can be contained inside the function?

library(fpp)
y <- (1:60)
z <- y + rnorm(60)
my.df <- data.frame(y,z)
NFcst <- 30

my.fcast <- fcast('y','z',my.df,NFcst) 

fcast <- function(a,b,df,h) {
  model <- paste(a,'~',b)
  x <- ts(data=df)  
  train.end <- time(x)[nrow(x)-h]
  test.start <- time(x)[nrow(x)-h+1]
  train <- window(x,end=train.end)
  test <- window(x,start=test.start)
  fit <- lm(model, data=train)
  my.fcast <- forecast(fit,test)   #error object 'train' not found
}

#If I move train to the global environment, there is no error
x <- ts(data=my.df)  
train.end <- time(x)[nrow(x)-NFcst]
train <- window(x,end=train.end)

my.fcast <- fcast2('y','z',my.df,NFcst)

fcast2 <- function(a,b,df,h) {
  model <- paste(a,'~',b)
  test.start <- time(x)[nrow(x)-h+1]
  test <- window(x,start=test.start)
  fit <- lm(model, data=train)
  my.fcast <- forecast(fit,test)   #no error
}

Upvotes: 2

Views: 3292

Answers (2)

User7598
User7598

Reputation: 1678

In addition to @James' answer. Your model is not properly defined. The argument model <- paste(a,'~',b) puts a ~ between all numbers in your data set.

It may be better to simply define model as an arguement in the function. Such as:

fcast <- function(model,df,h) { #define model outside of the function
  #model <- paste(a,'~',b) #commented out
  x <- ts(data=df)  
  train.end <- time(x)[nrow(x)-h]
  test.start <- time(x)[nrow(x)-h+1]
  train <- window(x,end=train.end)
  test <- window(x,start=test.start)
  fit <- lm(model, data=train)
  my.fcast <- forecast(fit,test)   #error object 'train' not found -> see @James' answer
}

This means your function would look like:

fcast(a~b,df,h)

Upvotes: 3

James
James

Reputation: 66874

It looks like it is a bug in forecast.lm which comes from this expression:

if (!is.null(object$data)) 
    origdata <- object$data
else if (!is.null(object$call$data)) 
    origdata <- object$data <- eval(object$call$data)
else origdata <- as.data.frame(fitted(object) + residuals(object))

The eval call seems to be doing strange things as noted in ?sys.parent:

Strictly, sys.parent and parent.frame refer to the context of the parent interpreted function. So internal functions (which may or may not set contexts and so may or may not appear on the call stack) may not be counted, and S3 methods can also do surprising things.

A quick fix for your function is the set the data into the lm object to avoid the eval call:

fcast <- function(a,b,df,h) {
  model <- paste(a,'~',b)
  x <- ts(data=df)  
  train.end <- time(x)[nrow(x)-h]
  test.start <- time(x)[nrow(x)-h+1]
  train <- window(x,end=train.end)
  test <- window(x,start=test.start)
  fit <- lm(model, data=train)
  fit$data <- train
  my.fcast <- forecast(fit,test)
}

Upvotes: 5

Related Questions