【问题标题】:Using auto.arima: Error in OCSBtest(x, m) : subscript out of bounds使用 auto.arima:OCSBtest(x, m) 中的错误:下标越界
【发布时间】:2012-06-09 13:22:15
【问题描述】:

我在大量时间序列上使用一个大(isplit)循环来测试 ARIMA 模型。为此,我使用了 forecast 包中的 auto.arima 函数。

为此,我创建了一个函数,用于遍历所有时间序列,同时跟踪进度并存储拟合模型和统计数据(例如准确性和模型参数)。现在我正在处理由auto.arima 函数生成的错误。更准确地说;由 OCSB 季节性测试引起的。

我将此函数用于“每月”时间序列以及“每周”时间序列。对于每月时间序列 a 没有问题(几乎 50000,包括很多“零”值)。对于每周时间序列,我遇到了问题。但我无法找到错误的真正原因。

我试图重现错误。我认为它与许多 0(或相同)值与 52 频率周期相结合有关。但我还是不能把矛头指向问题所在。

请参阅下面的示例。一些信息:时间序列集是每周值(freq=52),从 2010 年第 1 周开始。长度为 122 个样本(直到 2012 年第 18 周)。因此我测试了 122 的长度,我可以为此生成错误。我仍然认为这与频率和“运行相同的值”有关......

有些会产生错误,有些则不会。

示例1【随机数,长度=122】>没问题:

ts_element <- ts(sample(0:30, 122, replace=TRUE), frequency = 52, start = c(2010, 1))
fit <- auto.arima(ts_element, trace=FALSE, seasonal.test="ocsb", allowdrift=TRUE, stepwise=TRUE)

示例 2 [只有 0 个值,长度 = 122] > OCSB 测试错误(通常我会假设一个不同的错误...参见示例 3):

ts_element <- ts(sample(0:0, 122, replace=TRUE), frequency = 52, start = c(2010, 1))
fit <- auto.arima(ts_element, trace=FALSE, seasonal.test="ocsb", allowdrift=TRUE, stepwise=TRUE)
Error in OCSBtest(x, m) : subscript out of bounds

示例3 [只有0个值,长度=100] > '零/相等值'错误,我假设这个,这个例子不是问题,但要指出长度是相关的(与示例2比较):

ts_element <- ts(sample(0:0, 100, replace=TRUE), frequency = 52, start = c(2010, 1))
fit <- auto.arima(ts_element, trace=FALSE, seasonal.test="ocsb", allowdrift=TRUE, stepwise=TRUE)
Error in if (PVAL == min(tablep)) warning("p-value smaller than printed p-value") else warning("p-value greater     than printed p-value") : 
  missing value where TRUE/FALSE needed

示例 4 [与示例 3 几乎相同,但有一个非 0 值,长度 = 100] > 没有问题了:

ts_element[30] <- 1
fit <- auto.arima(ts_element, trace=FALSE, seasonal.test="ocsb", allowdrift=TRUE, stepwise=TRUE)

示例 5 [与示例 4 几乎相同,但长度=122] > OCSB 测试错误:

ts_element <- ts(sample(0:0, 122, replace=TRUE), frequency = 52, start = c(2010, 1))
ts_element[30] <- 1
fit <- auto.arima(ts_element, trace=FALSE, seasonal.test="ocsb", allowdrift=TRUE, stepwise=TRUE)
Error in OCSBtest(x, m) : subscript out of bounds

示例 6 [随机 1 和 0,长度=122] > 没问题:

ts_element <- ts(sample(0:1, 122, replace=TRUE), frequency = 52, start = c(2010, 1))
fit <- auto.arima(ts_element, trace=FALSE, seasonal.test="ocsb", allowdrift=TRUE, stepwise=TRUE)

例7【随机数,长度小于50】>没问题:

ts_element <- ts(sample(1:34, 50, replace=TRUE), frequency = 52, start = c(2010, 1))
fit <- auto.arima(ts_element, trace=FALSE, seasonal.test="ocsb", allowdrift=TRUE, stepwise=TRUE)

有人知道 OCSB 越界错误的原因是什么吗? 如何识别?

主要问题是,每当我在本文开头描述的函数中出现此错误时,该函数不会输出我收集的所有信息。因此,等待的时间是徒劳的。 因此,如果无法找到根本原因,我还可以通过一些代码来处理错误以“忽略”它们(跳过该时间序列)并走得更远。或者忽略,但仍然输出当时收集到的信息。

如何解决?

注意:零错误不是问题。我将在我的函数中介绍这一点。

【问题讨论】:

    标签: r


    【解决方案1】:

    很好的问题,并且解释得很好。您在提交之前清楚地考虑了这一点。

    您的示例中的问题是由于处理充满零的时间序列的一些问题(在我看来,是错误)。

    一般来说,您应该使用debug 命令来单步执行您的代码。例如,尝试调试为auto.arima 运行的五个主要函数:

    debug(auto.arima)
    debug(nsdiffs)
    debug(forecast:::OCSBtest)
    debug(lm)
    debug(lm.fit)
    

    (使用Q 退出并使用undebug 停止调试函数)然后尝试在示例2中运行您的代码

    ts_element <- ts(sample(0:0, 122, replace=TRUE), frequency = 52, start = c(2010, 1))
    fit <- auto.arima(ts_element, trace=FALSE, seasonal.test="ocsb", allowdrift=TRUE, stepwise=TRUE)
    

    在多次按下Enter 之后,您最终将到达 R 失败的地步。在这种情况下,这是lm.fit 中一个相当深刻和令人讨厌的错误。如果所有系数都为零,则出于某种原因,它将它们转换为NA。当OCSBtest 函数尝试提取系数时,它发现矩阵为空,并告诉您它不是一个合适的索引。

    我会告诉你将此报告给 R-bugs...但是当涉及到 base 中的错误时,他们可能会非常狡猾。他们可能会告诉您这是“用户错误”,您不应该将回归模型拟合为全零(叹气)。

    示例 3 的第一个问题似乎是 nsdiffs 页面中未记录的功能,该页面描述了 forecast::OCSBtest 函数。看起来您的时间序列必须大于周期的 2 倍 + 5,否则将不会运行季节性差异。在示例 2 中确实如此,但在 示例 3 中则不然。事实上,函数中的代码的最开始是:

    if (length(time.series) < (2 * period + 5)) {
        return(0)
    }
    

    阅读nsdiffs 页面中列出的两个奥斯本参考资料,也许它在某处提到它。让forecast 的作者知道是个好主意,这样他们就可以将其包含在文档中的某个地方。甚至可能会发出警告,并可选择将其关闭。

    示例 3 与 示例 2 的错误不同是因为 示例 3 立即退出 nsdiffs 函数,然后继续在进行差分的ndiff 函数中失败。 ndiff 似乎有一个错误,如果差的平方和为零(因为系列为零),则会导致除以零错误。下面是ndiff函数中的相关代码:

    s2 <- .C("R_pp_sum", as.vector(e, mode = "double"), as.integer(n), as.integer(l), s2 = as.double(s2), PACKAGE = "tseries")$s2
    STAT <- eta/s2 # Becomes NaN
    PVAL <- approx(table, tablep, STAT, rule = 2)$y # Also NaN
    if (is.na(approx(table, tablep, STAT, rule = 1)$y)) if (PVAL == 
    min(tablep)) warning("p-value smaller than printed p-value") else warning("p-value greater than printed p-value") # Bombs
    

    示例 4 成功,因为 s2 永远不会为零。一个简单的解决方法是在除法之前检查s2 是否为零。

    示例 5 失败的原因与 示例 2 大致相同。它进入nsdiff 函数,因为它的长度大于2*period+5,然后因为lm.fit 没有返回全为零的系数而失败。

    示例 6 成功,因为 lm.fit 现在将正确返回系数,因为它们并非全为零,因为您的时间序列混合了 1 和 0。

    示例 7 成功,因为 nsdiff 没有运行(因为系列太小)并且 ndiff 将不再导致除以零,因为平方差之和不会零。

    总之,您的示例显示了两个错误。一个在ndiff 中,当时间序列始终为零时,另一个在lm.fit 函数中,当协变量都为零时。此外,nsdiff 中的文档应该更新,告诉您如果时间序列的长度小于2*period+5,如果您使用 'ocsb' 选项,它将不会运行(但也许这在参考)。

    【讨论】:

    • 请注意,nsdiffs 文档中的引用存在错误。奥斯本的第二篇参考文献的标题应该是:“英国宏观经济变量的季节性调查”。我找不到对2*period+5 的任何引用。
    • 哇!伟大而广泛的答案。你真的花时间来分析这个。感谢那。这对我有很大帮助。一般来说,错误是由“很多零”引起的,所以这是我可以使用的信息。我现在使用tryCatch 来处理错误并存储有关这些错误的信息。
    • 向预测的作者报告这一点确实是个好主意。他们很快就会修复它,您不必编写代码来捕获错误。
    猜你喜欢
    • 2018-08-19
    • 2015-04-03
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 2015-02-11
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多