预测时间序列数据

geo*_*lly 25 r time-series xts

我做了一些研究,我一直在寻找解决方案.我有一个时间序列数据,非常基本的数据框,让我们称之为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
Run Code Online (Sandbox Code Playgroud)

我真的很感激任何帮助.我正在处理时间序列数据,需要能够根据历史数据创建预测.

  1. 首先我尝试将其转换为xts:

    x.xts <- xts(x$Used, x$Date)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后,我转换x.xts为常规时间序列:

    x.ts <- as.ts(x.xts)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将值放入ets:

    x.ets <- ets(x.ts)
    
    Run Code Online (Sandbox Code Playgroud)
  4. 进行了10个时期的预测:

    x.fore <- forecast(x.ets, h=10)
    
    Run Code Online (Sandbox Code Playgroud)
  5. x.fore 这是:

       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
    
    Run Code Online (Sandbox Code Playgroud)
  6. 当我尝试绘制时x.fore,我得到一个图形,但x轴显示数字而不是日期:

在此输入图像描述

我正在做的步骤是否正确?如何更改x轴以读取显示日期?

我非常感谢你的任何意见.

A5C*_*2T1 43

这是我做的:

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))
Run Code Online (Sandbox Code Playgroud)

导致:

示例输出

我们可以从中学到什么:

  • 您可以组合许多步骤,减少您创建的中间对象的数量
  • 输出仍然不如@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))
Run Code Online (Sandbox Code Playgroud)

这给出了与上图完全相同的结果.

更新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)
Run Code Online (Sandbox Code Playgroud)

哪个会产生:

第二次尝试

原始代码中的部分问题是,在将数据转换为xts对象并将其转换为ts对象后,您将丢失forecast点中的日期.

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

> 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
Run Code Online (Sandbox Code Playgroud)

希望这有助于您了解原始方法的问题,并通过处理R中的时间序列来提高您的能力.

更新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)
Run Code Online (Sandbox Code Playgroud)

导致:

最后的情节

请注意标识ts对象开始日期的替代方法.


Joã*_*iel 8

如果您对特定型号没有任何偏好,我建议您使用适用于各种情况的偏好:

library(forecast)
t.ser <- ts(used, start=c(2011,1), freq=12)
t.ets <- ets(t.ser)
t.fc <- forecast(t.ets,h=10)
Run Code Online (Sandbox Code Playgroud)

这将为您提供未来10个月的预测.

更具技术性,它使用指数平滑法,这是一般情况下的一个很好的选择.根据数据的类型,可能会有一个更适合您使用的模型,但这ets是一个很好的一般选择.

重要的是要强调,由于您没有完成两个周期(少于24个月),因此该模型无法检测到骚动,因此不会将其包含在计算中.


jor*_*ran 7

通过简单地抑制原始图中的轴然后自己绘制它们来改变绘图来显示日期是相当容易的:

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)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 我可以在一定程度上理解为什么@mikesmith的这个问题经常被投票,但我觉得有点宽容,因为除非你在R中做了几个时间序列图(并且从你的网站我可以看到你已经完成*很多*),我可以看到它很容易卡住.没有太多的经验或需要在R中使用日期格式,它确实花了我至少一点时间谷歌搜索来找出处理来自不同R包的日期的不同选项; 希望Mike在未来做同样的事情,而不是牺牲这么多的声誉! (3认同)
  • @mrdwab 首先,我应该说重读我的评论我很后悔它的语气。我感到沮丧的不是 R 中 OP 的能力水平,而是他清楚地提出问题和解释问题的能力。即便如此,让这种挫败感渗透到我的评论中也是不合适的。 (3认同)