Search code examples
rdplyrforecasting

Error in ts(x) : 'ts' object must have one or more observations


When I do forecast using forecast library, I noticed following code does not run as expected:

library(forecast)
library(dplyr)
df1 <- data.frame(gp=gl(20,5), dt=seq(1:100))

get <- function (df1){
  ts1 <- ts((df1%>%filter(gp==2))$dt)
  as.numeric(forecast(ar(ts1),15)$mean)
}    

print(get(df1))

The error return is:

Error in ts(x) : 'ts' object must have one or more observations

May be it is caused by ar or ar.burg function. Because if you change the function to ets or something else the function works well.

What is more strange is that if you change the code to:

library(forecast)
library(dplyr)
df1 <- data.frame(gp=gl(20,5), dt=seq(1:100))
ts1 <- ts((df1%>%filter(gp==2))$dt)

get <- function (ts1){
  as.numeric(forecast(ar(ts1),15)$mean)
}


print(get(ts1))

The code is also running correctly. I think this may be a bug in ar function, and the problem is somehow related to scope. Any thoughts about this?


Solution

  • The problem is to do with scoping. forecast() tries to find the time series used to fit the model. The functions from the forecast package (such as ets) store this information in the model object, so it is easy for forecast() to find it. But ar() is from the stats package, and it does not store the time series used to fit the model. So forecast() goes looking for it. If you run your code outside of the get() function, it works ok because forecast() manages to find the ts1 object in the local environment. But within the get() function it causes an error.

    One simple fix is to add the information to the fitted model before calling forecast:

    library(forecast)
    library(dplyr)
    df1 <- data.frame(gp=gl(20,5), dt=seq(1:100))
    ts1 <- ts((df1%>%filter(gp==2))$dt)
    
    get <- function (ts1){
      fit <- ar(ts1)
      fit$x <- ts1
      as.numeric(forecast(fit,15)$mean)
    }
    
    print(get(ts1))
    

    Alternatively, use predict instead of forecast:

    library(dplyr)
    df1 <- data.frame(gp=gl(20,5), dt=seq(1:100))
    ts1 <- ts((df1%>%filter(gp==2))$dt)
    
    get <- function (ts1){
      fit <- ar(ts1)
      as.numeric(predict(fit,n.ahead=15)$pred)
    }
    
    print(get(ts1))