如何获得 highcharter 来表示预测对象?

Posted

技术标签:

【中文标题】如何获得 highcharter 来表示预测对象?【英文标题】:How can I get highcharter to represent a forecast object? 【发布时间】:2017-08-28 13:26:48 【问题描述】:

这是this question 的后续。

我正在尝试让该问题中给出的管道接受预测对象作为输入:

再次,使用这些数据:

> dput(t)
structure(c(2, 2, 267822980, 325286564, 66697091, 239352431, 
94380295, 1, 126621669, 158555699, 32951026, 23, 108000151, 132505189, 
29587564, 120381505, 25106680, 117506099, 22868767, 115940080, 
22878163, 119286731, 22881061), .Dim = c(23L, 1L), index = structure(c(1490990400, 
1490994000, 1490997600, 1491001200, 1491004800, 1491008400, 1491012000, 
1491026400, 1491033600, 1491037200, 1491040800, 1491058800, 1491062400, 
1491066000, 1491069600, 1491073200, 1491076800, 1491109200, 1491112800, 
1491120000, 1491123600, 1491156000, 1491159600), tzone = "US/Mountain", tclass = c("POSIXct", 
"POSIXt")), class = c("xts", "zoo"), .indexCLASS = c("POSIXct", 
"POSIXt"), tclass = c("POSIXct", "POSIXt"), .indexTZ = "US/Mountain", tzone = "US/Mountain", .CLASS = "double", .Dimnames = list(
    NULL, "count"))

我用

highchart(type = 'stock') %>% 
    hc_add_series(t) %>% 
    hc_xAxis(type = 'datetime')

创造

但如果我按照同样的方法使用

require("forecast")
t.arima <- auto.arima(t)
x <- forecast(t.arima, level = c(95, 80))

highchart(type = 'stock') %>% 
     hc_add_series(x) %>%
     hc_xAxis(type = 'datetime')

我收到此错误:

Error in as.Date.ts(.) : unable to convert ts time to Date class

如何将预测系列与历史数据一起显示?我在文档中看到了这一点,但不明白为什么会出现此错误。

JK 的 JS 控制台输出: 重新索引后的 DF 数据:

dput(df)
structure(list(Index = structure(c(1490968800, 1490972400, 1490976000, 
1490979600, 1490983200, 1490986800, 1490990400, 1491004800, 1491012000, 
1491015600, 1491019200, 1491037200, 1491040800, 1491044400, 1491048000, 
1491051600, 1491055200, 1491087600, 1491091200, 1491098400, 1491102000, 
1491134400, 1491138000, 1491217200, 1491220800, 1491224400, 1491228000, 
1491231600, 1491235200, 1491238800, 1491242400, 1491246000, 1491249600, 
1491253200, 1491256800, 1491260400, 1491264000, 1491267600), class = c("POSIXct", 
"POSIXt")), Data = c(2, 2, 259465771, 315866206, 64582553, 233440220, 
91918347, 1, 126563786, 158555699, 32951026, 23, 108000151, 132505189, 
29587564, 120381505, 25106680, 117506099, 22868767, 115898351, 
22878163, 119285747, 22881061, 157925588, 32447780, 223096830, 
281656273, 45406684, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), 
    Fitted = c(102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, 102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, 102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, 102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, 102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, 102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, 102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), 
    `Point Forecast` = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, 102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, 102170573.857143, 102170573.857143, 102170573.857143, 
    102170573.857143, 102170573.857143, 102170573.857143), `Lo 80` = c(NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -16003477.5789723, 
    -16003477.5789723, -16003477.5789723, -16003477.5789723, 
    -16003477.5789723, -16003477.5789723, -16003477.5789723, 
    -16003477.5789723, -16003477.5789723, -16003477.5789723), 
    `Hi 80` = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, 220344625.293258, 220344625.293258, 220344625.293258, 
    220344625.293258, 220344625.293258, 220344625.293258, 220344625.293258, 
    220344625.293258, 220344625.293258, 220344625.293258), `Lo 95` = c(NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -78561041.5917782, 
    -78561041.5917782, -78561041.5917782, -78561041.5917782, 
    -78561041.5917782, -78561041.5917782, -78561041.5917782, 
    -78561041.5917782, -78561041.5917782, -78561041.5917782), 
    `Hi 95` = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, 282902189.306064, 282902189.306064, 282902189.306064, 
    282902189.306064, 282902189.306064, 282902189.306064, 282902189.306064, 
    282902189.306064, 282902189.306064, 282902189.306064)), .Names = c("Index", 
"Data", "Fitted", "Point Forecast", "Lo 80", "Hi 80", "Lo 95", 
"Hi 95"), row.names = c(NA, -38L), class = "data.frame")

【问题讨论】:

我去看看 【参考方案1】:

不确定这是由于时间序列不规则造成的。

无论如何,ggfortify:::fortify.forecast 是你的朋友。为什么?因为fortify(尝试)转换数据帧中的所有 R 对象。所以:

library(highcharter)
library(forecast)
t.arima <- auto.arima(t)
x <- forecast(t, level = c(95, 80))

library(highcharter)
library(ggplot2)
library(ggfortify)
#> 
#> Attaching package: 'ggfortify'
#> The following object is masked from 'package:forecast':
#> 
#>     gglagplot
class(x)
#> [1] "forecast"

df <- fortify(x)
head(df)
#>   Index      Data    Fitted Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
#> 1     1         2 140658844             NA    NA    NA    NA    NA
#> 2  3601         2 121734145             NA    NA    NA    NA    NA
#> 3  7201 267822980 105355638             NA    NA    NA    NA    NA
#> 4 10801 325286564 127214522             NA    NA    NA    NA    NA
#> 5 14401  66697091 153863779             NA    NA    NA    NA    NA
#> 6 18001 239352431 142136089             NA    NA    NA    NA    NA

现在你可以:

highchart(type = "stock") %>% 
  hc_add_series(df, "line", hcaes(Index, Data), name = "Original") %>% 
  hc_add_series(df, "line", hcaes(Index, Fitted), name = "Fitted") %>%
  hc_add_series(df, "line", hcaes(Index, `Point Forecast`), name = "Forecast") %>% 
  hc_add_series(df, "arearange", hcaes(Index, low = `Lo 80`, high = `Hi 80`), name = "Interval") 

如您所见,fortify 也无法检测到实时时间。所以你需要在你想要的时候转换索引。

【讨论】:

因此,如果我使用 df$Index &lt;- c(zoo::index(t)+7614000, (max(zoo::index(t))+7614000+3600*1:10)) 重新格式化索引以使其与 2017-03-31 和 10 小时预测前沿对齐,然后我重新运行此代码,返回的图形为空白。 在 chrome 中打开小部件,按 F12 并检查 javascript 控制台 好的,我使用了df$Index &lt;- c(zoo::index(t), (max(zoo::index(t)) + 3600*1:10)),并在问题中添加了 js 控制台的快照。看起来是一个空的 svg.highcharts-root 对象。 是 NA 的问题吗?我也在问题中添加了df 的当前状态 这不是 NA 的问题,我将它们全部替换为 1,它仍然没有呈现...【参考方案2】:

错误

Error in as.Date.ts(.) : unable to convert ts time to Date class

是因为您有一个频率未被函数as.Date.ts(.) 覆盖的 ts 对象。当我们看到这个函数做了什么,这就是我们得到的:

function (x, offset = 0, ...) 

    time.x <- unclass(time(x)) + offset
    if (frequency(x) == 1) 
        as.Date(paste(time.x, 1, 1, sep = "-"))
    else if (frequency(x) == 4) 
        as.Date(paste((time.x + 0.001)%/%1, 3 * (cycle(x) - 1) + 
            1, 1, sep = "-"))
    else if (frequency(x) == 12) 
        as.Date(paste((time.x + 0.001)%/%1, cycle(x), 1, sep = "-"))
    else stop("unable to convert ts time to Date class")

此函数仅考虑 ts 对象的频率的 3 个值:1、4 或 12。当我们查看您的对象 x 的频率时,我们看到它的 frequency = 0.000277777777777778,所以当 highcharter使用 x 中的 ts 对象调用该函数,它会停止并给您该错误。

关于如何“修复”它,我们有两种选择:

    在运行auto.arimaforecastfrequency = 1 之前t 转换为ts 对象(而不是xts 对象); 运行auto.arimaforecast后,我们可以为未来的日期创建一个索引,并将x中的ts对象转换为具有正确索引的xts对象。

我说“修复”是因为这些解决方案并不完美,我们将会看到。

选项 1

t <- structure(
  c(2, 2, 267822980, 325286564, 66697091, 239352431,
    94380295, 1, 126621669, 158555699, 32951026, 23, 
    108000151, 132505189, 29587564, 120381505, 25106680,
    117506099, 22868767, 115940080, 22878163, 119286731, 
    22881061), 
  .Dim = c(23L, 1L), 
  index = structure(c(1490990400, 1490994000, 1490997600, 
                      1491001200, 1491004800, 1491008400, 
                      1491012000, 1491026400, 1491033600, 
                      1491037200, 1491040800, 1491058800, 
                      1491062400, 1491066000, 1491069600, 
                      1491073200, 1491076800, 1491109200, 
                      1491112800, 1491120000, 1491123600, 
                      1491156000, 1491159600), 
                    tzone = "US/Mountain", 
                    tclass = c("POSIXct","POSIXt")), 
  class = c("xts", "zoo"), 
  .indexCLASS = c("POSIXct","POSIXt"), 
  tclass = c("POSIXct", "POSIXt"), 
  .indexTZ = "US/Mountain", 
  tzone = "US/Mountain", 
  .CLASS = "double", 
  .Dimnames = list(NULL, "count"))


require("forecast")
library(highcharter)


# SOLUTION 1
t.tmp <- ts(t, start=1, end = length(t))
t.arima.1 <- auto.arima(t.tmp)
x.1 <- forecast(t.arima.1, level = c(95, 80))

highchart(type = 'stock') %>% 
  hc_add_series(x.1) %>%
  hc_add_series(x.1$x, name = "Original") %>% 
  hc_add_series(x.1$fitted, name = "Fitted")

这种方法的问题是我们丢失了日期(轴、工具​​提示等)。

选项 2,第一次尝试:每小时预测

我尝试为未来值创建一个每小时索引,但由于某种原因,Highcharter 将间隔向左移动(或者我看不到/弄清楚日期有一些问题)。

选项 2,第二次尝试:每日预测

当我将其更改为未来值的每日索引时,它起作用了,但这很奇怪,因为我们有每小时的观察结果,而且我们绘图的预测部分显示“每日预测”。

这里是完整的代码:

t <- structure(
  c(2, 2, 267822980, 325286564, 66697091, 239352431,
    94380295, 1, 126621669, 158555699, 32951026, 23, 
    108000151, 132505189, 29587564, 120381505, 25106680,
    117506099, 22868767, 115940080, 22878163, 119286731, 
    22881061), 
  .Dim = c(23L, 1L), 
  index = structure(c(1490990400, 1490994000, 1490997600, 
                      1491001200, 1491004800, 1491008400, 
                      1491012000, 1491026400, 1491033600, 
                      1491037200, 1491040800, 1491058800, 
                      1491062400, 1491066000, 1491069600, 
                      1491073200, 1491076800, 1491109200, 
                      1491112800, 1491120000, 1491123600, 
                      1491156000, 1491159600), 
                    tzone = "US/Mountain", 
                    tclass = c("POSIXct","POSIXt")), 
  class = c("xts", "zoo"), 
  .indexCLASS = c("POSIXct","POSIXt"), 
  tclass = c("POSIXct", "POSIXt"), 
  .indexTZ = "US/Mountain", 
  tzone = "US/Mountain", 
  .CLASS = "double", 
  .Dimnames = list(NULL, "count"))

require("forecast")
library(highcharter)
library(xts)

t.arima <- auto.arima(t)
x <- forecast(t.arima, level = c(95, 80))

# Problem 

## Time from 'forecast'
time.x <- time(x$mean) # ts variable
time.x # see that frequency = 0.000277777777777778

## Original time
time.t <- time(t) # POSIXct variable, use as.ts to see frequency
as.ts(time.t) # frequency = 1

## Try to transform back to formatted date
as.POSIXct(as.double(time.t), tz = "US/Mountain", origin = "1970-01-01")
as.POSIXct(as.double(time.x), tz = "US/Mountain", origin = "1970-01-01")

#--------------------------------------------------------#

# SOLUTION 1
t.tmp <- ts(t, start=1, end = length(t))
t.arima.1 <- auto.arima(t.tmp)
x.1 <- forecast(t.arima.1, level = c(95, 80))

highchart(type = 'stock') %>% 
  hc_add_series(x.1) %>%
  hc_add_series(x.1$x, name = "Original") %>% 
  hc_add_series(x.1$fitted, name = "Fitted")

#------------------------------------------------------#

# SOLUTION 2 - With correct dates but wrong plot

## Create new forecast variable
x.2 <- forecast(t.arima.1, level = c(95, 80))

## Take forecast length
forecast.length <- length(time.x)

### Create New Forecast dates (HOUR)
### Since I don't know the exact forecast times, I'll add one HOUR
### for each obs starting from the last date in the original dataset 

last.date <- time.t[length(time.t)]

new.forecast.time.hour <- as.POSIXct(last.date) + c((1:forecast.length)*3600)

## Insert date back

x.2$mean  <- xts(x.1$mean, order.by = new.forecast.time.hour)
x.2$lower <- xts(x.1$lower, order.by = new.forecast.time.hour)
x.2$upper <- xts(x.1$upper, order.by = new.forecast.time.hour)

### Original Data
x.2$x <- xts(x.1$x, order.by = time.t)

### Fitted
x.2$fitted <- xts(x.1$fitted, order.by = time.t)

# Plot forecasts with correct date

highchart(type = 'stock') %>% 
  hc_add_series(x.2) %>%
  hc_add_series(x.2$x, name = "Original") %>% 
  hc_add_series(x.2$fitted, name = "Fitted") %>%
  hc_xAxis(type = 'datetime')

#------------------------------------------------------#

# SOLUTION 3 - Correct plot but only for daily forecasts

## Create new forecast variable
x.3 <- forecast(t.arima.1, level = c(95, 80))

## Take forecast length
forecast.length <- length(time.x)

### Create New Forecast dates (DAY)
### Since I don't know the exact forecast times, I'll add one DAY
### for each obs starting from the last date in the original dataset 

last.date <- time.t[length(time.t)]

new.forecast.time.day <- as.POSIXct(last.date) + c((1:forecast.length)*3600*24)
## Add change from as.POSIXct to as.Date
new.forecast.time.day <- as.Date(new.forecast.time.day)

## Insert date back

x.3$mean  <- xts(x.1$mean, order.by = new.forecast.time.day)
x.3$lower <- xts(x.1$lower, order.by = new.forecast.time.day)
x.3$upper <- xts(x.1$upper, order.by = new.forecast.time.day)

### Original Data
x.3$x <- xts(x.1$x, order.by = time.t)

### Fitted
x.3$fitted <- xts(x.1$fitted, order.by = time.t)

# Plot forecasts with correct date

highchart(type = 'stock') %>% 
  hc_add_series(x.3) %>%
  hc_add_series(x.3$x, name = "Original") %>% 
  hc_add_series(x.3$fitted, name = "Fitted") %>%
  hc_xAxis(type = 'datetime')

另一件事:我的图上的拟合值与 jbkunst 图上的拟合值不同,因为他直接在 t 上使用了 forecast,而不是在 t.arima 上(只是一个错字,我相信)。这样,我的预测基于 Arima 模型,而他的预测基于 ETS 模型。

【讨论】:

以上是关于如何获得 highcharter 来表示预测对象?的主要内容,如果未能解决你的问题,请参考以下文章

highcharts中用<%=%>获得一个数组,如何将该数组赋给data呀?????

在 gbm 多项式分布中,如何使用预测来获得分类输出? [复制]

如何使用带有词嵌入的 Keras LSTM 来预测词 id

使用 d3.js/chart.js/highcharts 在实际和预测散点图中的 R 平方最佳拟合线

如何使用Keras LSTM与word嵌入来预测单词id

highcharts怎么以x轴的值作为条件查询数据库,结果显示在tooltip中