预测时间序列数据

26

我是一名有帮助的助手,能够翻译文本。

以下是需要翻译的内容:

我已经做了一些调查,但无法找到解决方案。我有一个时间序列数据,非常基本的数据框,我们称之为 x:

Date        Used
11/1/2011   587
11/2/2011   578
11/3/2011   600
11/4/2011   599
11/5/2011   678
11/6/2011   555
11/7/2011   650
11/8/2011   700
11/9/2011   600
11/10/2011  550
11/11/2011  600
11/12/2011  610
11/13/2011  590
11/14/2011  595
11/15/2011  601
11/16/2011  700
11/17/2011  650
11/18/2011  620
11/19/2011  645
11/20/2011  650
11/21/2011  639
11/22/2011  620
11/23/2011  600
11/24/2011  550
11/25/2011  600
11/26/2011  610
11/27/2011  590
11/28/2011  595
11/29/2011  601
11/30/2011  700
12/1/2011   650
12/2/2011   620
12/3/2011   645
12/4/2011   650
12/5/2011   639
12/6/2011   620
12/7/2011   600
12/8/2011   550
12/9/2011   600
12/10/2011  610
12/11/2011  590
12/12/2011  595
12/13/2011  601
12/14/2011  700
12/15/2011  650
12/16/2011  620
12/17/2011  645
12/18/2011  650
12/19/2011  639
12/20/2011  620
12/21/2011  600
12/22/2011  550
12/23/2011  600
12/24/2011  610
12/25/2011  590
12/26/2011  750
12/27/2011  750
12/28/2011  666
12/29/2011  678
12/30/2011  800
12/31/2011  750

我非常感谢您的帮助。我正在处理时间序列数据,需要根据历史数据创建预测。

  1. First I tried to convert it to xts:

    x.xts <- xts(x$Used, x$Date)
    
  2. Then, I converted x.xts to regular time series:

    x.ts <- as.ts(x.xts)
    
  3. Put the values in ets:

    x.ets <- ets(x.ts)
    
  4. Performed forecasting for 10 periods:

    x.fore <- forecast(x.ets, h=10)
    
  5. x.fore is this:

       Point Forecast    Lo 80    Hi 80    Lo 95    Hi 95
    87       932.9199 831.7766 1034.063 778.2346 1087.605
    88       932.9199 818.1745 1047.665 757.4319 1108.408
    89       932.9199 805.9985 1059.841 738.8103 1127.029
    90       932.9199 794.8706 1070.969 721.7918 1144.048
    91       932.9199 784.5550 1081.285 706.0153 1159.824
    92       932.9199 774.8922 1090.948 691.2375 1174.602
    93       932.9199 765.7692 1100.071 677.2849 1188.555
    94       932.9199 757.1017 1108.738 664.0292 1201.811
    95       932.9199 748.8254 1117.014 651.3717 1214.468
    96       932.9199 740.8897 1124.950 639.2351 1226.605
    
  6. When I try to plot the x.fore, I get a graph but the x-axis is showing numbers rather than dates:

enter image description here

我正在执行的步骤是正确的吗?如何将x轴更改为显示日期?

非常感谢您的任何意见。


5
你能说明一下你所做的研究吗?install.packages("forecast"); library("sos"); findFn("forecast"); findFn("forecast time-series") - Ben Bolker
请展示您用于尝试绘制数据的代码(?dput 可以帮助您提供可重现的示例,请参见 http://tinyurl.com/reproducible-000)。 - Ben Bolker
@ben,我修改了我的原始帖子。你觉得怎么样? - george willy
3个回答

45

我所做的是:

x$Date = as.Date(x$Date,format="%m/%d/%Y")
x = xts(x=x$Used, order.by=x$Date)
# To get the start date (305)
#     > as.POSIXlt(x = "2011-11-01", origin="2011-11-01")$yday
##    [1] 304
# Add one since that starts at "0"
x.ts = ts(x, freq=365, start=c(2011, 305))
plot(forecast(ets(x.ts), 10))

因此得到的结果为:

Example output

我们可以从中学到什么:

  • 许多步骤可以合并,从而减少创建中间对象的数量。
  • 输出结果仍不像@joran那样漂亮,但仍然易于阅读。2011.85表示“第365*.85天”(即当年的第310天)。
  • 可以使用 as.POSIXlt(x = "2011-11-01", origin="2011-11-01")$yday 来确定一年中的某一天,并且可以使用类似 as.Date(310, origin="2011-01-01") 的方法来确定日期。

更新

您甚至可以删除更多的中间步骤,因为没有理由先将数据转换为 xts 格式。

x = ts(x$Used, start=c(2011, as.POSIXlt("2011-11-01")$yday+1), frequency=365)
# NOTE: We have only selected the "Used" variable 
# since ts will take care of dates
plot(forecast(ets(x), 10))

这会得到与上面的图片完全相同的结果。

更新2

在@joran提供的解决方案基础上,你可以尝试:

# 'start' calculation = `as.Date("2011-11-01")-as.Date("2011-01-01")+1`
# No need to convert anything to dates at this point using xts
x = ts(x$Used, start=c(2011, 305), frequency=365)
# Directly plot your forecast without your axes
plot(forecast(ets(x), 10), axes = FALSE)
# Generate labels for your x-axis
a = seq(as.Date("2011-11-01"), by="weeks", length=11)
# Plot your axes.
# `at` is an approximation--there's probably a better way to do this, 
# but the logic is approximately 365.25 days in a year, and an origin
# date in R of `January 1, 1970`
axis(1, at = as.numeric(a)/365.25+1970, labels = a, cex.axis=0.6)
axis(2, cex.axis=0.6)

这将产生:

Second attempt

你原来的代码存在一个问题,即在将数据转换为 xts 对象并将其转换为 ts 对象后,在 forecast 点中丢失了日期。

请将 x.fore 输出的第一列 (Point) 与以下内容进行比较:

> forecast(ets(x), 10)
         Point Forecast    Lo 80    Hi 80    Lo 95    Hi 95
2012.000       741.6437 681.7991 801.4884 650.1192 833.1682
2012.003       741.6437 676.1250 807.1624 641.4415 841.8459
2012.005       741.6437 670.9047 812.3828 633.4577 849.8298
2012.008       741.6437 666.0439 817.2435 626.0238 857.2637
2012.011       741.6437 661.4774 821.8101 619.0398 864.2476
2012.014       741.6437 657.1573 826.1302 612.4328 870.8547
2012.016       741.6437 653.0476 830.2399 606.1476 877.1399
2012.019       741.6437 649.1202 834.1672 600.1413 883.1462
2012.022       741.6437 645.3530 837.9345 594.3797 888.9078
2012.025       741.6437 641.7276 841.5599 588.8352 894.4523

更新3

最终、更加准确的解决方案--因为我正在避开实际上应该做的其他工作...

使用lubridate包来更好地处理日期:

require(lubridate)
y = ts(x$Used, start=c(2011, yday("2011-11-01")), frequency=365)
plot(forecast(ets(y), 10), xaxt="n")
a = seq(as.Date("2011-11-01"), by="weeks", length=11)
axis(1, at = decimal_date(a), labels = format(a, "%Y %b %d"), cex.axis=0.6)
abline(v = decimal_date(a), col='grey', lwd=0.5)

导致结果如下:

最终图

请注意识别您的ts对象的开始日期的替代方法。


在将半小时数据转换为时间序列时,频率(frequency)和起始时间(start)的值会是什么? - Ashish Anand

9
如果您没有对特定型号有任何偏好,我建议您使用适用于各种情况的模型:
library(forecast)
t.ser <- ts(used, start=c(2011,1), freq=12)
t.ets <- ets(t.ser)
t.fc <- forecast(t.ets,h=10)

这将为您提供接下来10个月的预测结果。
更加技术化地说,它使用指数平滑法,这是一种适用于一般情况的良好选择。根据数据类型的不同,可能会有更好的特定于您使用的模型,但是ets是一个很好的通用选择。
需要强调的是,由于您没有完成两个周期(少于24个月),该模型无法检测季节性,因此不会包括在计算中。

你如何将它们放入图表中? - george willy
在绘制f.fc图后,我发现x轴的值为2011.1、2011.2等。如何格式化x轴以显示为1/2011、2/2012或者甚至是jan-2011、feb-2012等? - george willy

8

通过抑制原始图中的轴并自己绘制,改变绘图以显示日期是相当容易的:

plot(x.fore,axes = FALSE)
axis(2)
axis(1,at = pretty(1:72,n = 6),
       labels = (x$Date[1]-1) + pretty(1:72,n = 6),
       cex.axis = 0.65)

enter image description here


现在我遇到了这个错误:x.ets <- ets(x.ts) Error in rep(alpha + beta - alpha * phi, m - 2) : invalid 'times' argument 此外还有一个警告信息: In ets(x.ts) : I can't handle data with frequency less than 1. Seasonality will be ignored. - george willy
我遇到了这个错误:Error in $.zoo(x, Date) : 只有带有列名的zoo系列才可能。 - george willy
1
@mikesmith,你对我的回答提供了代码,它从你问题中的代码(使用x.fore)开始,但你抱怨在之前的步骤中出现错误,而这些错误在你的问题中从未提到?你能理解为什么你的问题一直被投票否决吗? - joran
4
我能够在一定程度上理解为什么@mikesmith的这个问题经常被投票否决,但我觉得更加宽容,因为除非你在R中完成了几个时间序列图(从您的网站可以看出您完成了很多),否则很容易被卡住。由于我没有在R中使用日期格式的很多经验和需求,所以我花了一些时间在谷歌上搜索不同R软件包处理日期的选项;希望未来Mike也能做同样的事情,而不是牺牲自己的声誉! - A5C1D2H2I1M1N2O1R2T1
3
首先,我应该说重新阅读我的评论后,我对它的语气感到遗憾。我的挫败感并不是因为OP在R方面的能力水平,而是他清楚地提出问题和解释他的问题的能力。即使这样,让我的挫败感渗透到评论中是不恰当的。 - joran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接