derekn derekn - 23 days ago 10
R Question

could not convert index to appropriate type while attempting to plot weekly ts object in dygraphs

I'm trying to create a Holt-Winters forecast from a weekly time series, then plot the original series and forecast using dygraphs. I have 144 weeks of friday week-ending data. For my purpose, I'm ignoring that some years have 53 weeks. The structure of the data can be simulated by:

## create data similar to what I have

week_date <- seq.Date(from = as.Date("2012/05/11"),
by = "week",
length.out = 144)
var1 <- diffinv(rnorm(143))
df <- data.frame(cbind(week_date, var1))

## convert to ts object then
## create Holt Winters forecast

dfts <- ts(df[,2],freq=52, start=c(2012,19))

hw <- HoltWinters(dfts)
p <- predict(hw, 4)
all <- cbind(dfts, p)

## create plots

dygraph(all, "time series dygraph") %>%
dySeries("var1", label = "Actual") %>%
dySeries(c("p.lwr", "", "p.upr"), label = "Predicted")

This produces the following error:

Error in as.xts.ts(data) : could not convert index to appropriate type

I tried the solution proposed here, but am getting the same error:

> all <- cbind(dfts = as.xts(dfts), p = as.xts(p))
Error in as.xts.ts(dfts) : could not convert index to appropriate type

Answer Source

There are a few things going on here. The root of the issue is that the data parameter of dygraph requires "Time series data (must be an xts object or an object which is convertible to xts)" (see ?dygraph).

As you've discovered, converting dfts to an xts object fails:

> library(xts)
> dfts <- as.xts(dfts)
Error in as.xts.ts(dfts) : could not convert index to appropriate type 

If you try to create the xts object directly:

> dfts <- xts(dfts)
Error in xts(dfts) : requires an appropriate time-based object

This is because, by default xts uses index(x) for the parameter. From ?xts:    a corresponding vector of unique times/dates - 
            must be of a known time-based class
Currently acceptable classes include: ‘Date’, ‘POSIXct’, ‘timeDate’, 
as well as ‘yearmon’ and ‘yearqtr’ where the index values remain unique.

And if you look at the index on dfts:

> str(index(dfts))
 num [1:148] 2012 2012 2012 2012 2012 ...

> head(index(dfts))
[1] 2012.346 2012.365 2012.385 2012.404 2012.423 2012.442

The index is numeric, while xts requires some type of date object, so you'll need to convert it.

First, I'd create the all object by converting each to a zoo object and then merging:

> library(zoo)
> # You'll need prediction.interval=TRUE to get the bounds:
> p <- predict(hw, 4, prediction.interval=TRUE)
> all <- merge(actual=as.zoo(dfts), predicted=as.zoo(p))
> head(all)
             actual fit upr lwr
2012(19)  0.0000000  NA  NA  NA
2012(20) -0.6264538  NA  NA  NA
2012(21) -0.4428105  NA  NA  NA
2012(22) -1.2784391  NA  NA  NA
2012(23)  0.3168417  NA  NA  NA
2012(24)  0.6463495  NA  NA  NA

Then, you can cast it to an xts object by converting the decimal index to a date. There are a few ways to do this, but the easiest is probably to use the date_decimal function from the lubridate package:

> library(lubridate)
> all.xts <- xts(all, date_decimal(index(all)))

Now, tweaking the parameters in the dygraph function:

> dygraph(all.xts, "time series dygraph") %>%
      dySeries("actual", label = "Actual") %>%
      dySeries(c("lwr", "fit", "upr"), label = "Predicted")

dygraph output