因此,错误来自于
predict.ar
。如果你运行
?predict
,你会发现它是一个通用函数,"
调用依赖于第一个参数的类的特定方法"。
所以,
class(output)
[1] "ar"
并且
methods(predict)
告诉您我们正在寻找第一种方法。
下一步尝试是在该方法中查找错误消息。上一个操作告诉我们
predict.ar
是不可见函数,因此我们需要结合
getAnywhere
和
capture.output
以及一些正则表达式函数来查找错误消息,但不幸的是这样做行不通。
grep("array", capture.output(getAnywhere("predict.ar")))
这意味着错误来自于预测函数predict.ar
内部运行的其他函数。
(正如@hadley所提到的)我们需要使用traceback()
来识别导致错误的内部函数。
predict(output, n.ahead = 2, se.fit = F)
traceback()
这很好地展示了我们的函数调用工作流程:
调用
predict
-> 识别对象的类并调用相应的方法
predict.ar
-> 使用
sweep
将预先分配的矩阵(大小为
ncol(x)
*
n.ahead
)与使用均值中心化数据的矩阵
rbind
-> 在使用
sweep
进行均值中心化数据时,转置一些
array
并创建一个新的
array
,而最后一个操作则返回错误。
所以基本上所有
sweep
函数所做的就是从
yz
中减去
yz
的平均值(即进行均值中心化-可以通过运行
scale(yz, scale = FALSE)
来完成,因此不确定为什么他们首先使用
sweep
。也许是为了特殊情况
dmean = FALSE
?)。在您的情况下,您指定了
dmean = FALSE
,因此它会从两列中删除零(这是非常不必要的操作,可能应该在这种情况下避免)。比较一下。
all.equal(t(t(yz) - colMeans(yz)), sweep(yz, 2L, colMeans(yz)))
唯一的问题是sweep
操作针对的是数组,因此它会尝试将您的数据转换为一个数组,并通过从yz
传递dim
属性来指定正确的维度,以创建一个array
供进一步操作使用,如下:
dims <- dim(yz)
perm <- c(2L, seq_along(dims)[-2L])
array(colMeans(yz), dims[perm])
矩阵非常适合这种操作,因为按定义所有矩阵都有一个“dim”属性。
虽然数据框没有“dim”属性,但“dim(x)”函数仍然足够聪明,可以自己计算“dim”,所以这个方法完全可行。
dim(x)
唯一的问题是,
predict.ar
函数在到达
sweep
之前,在某个过程中从
x
中剥离了
class
属性,因此这就是
matrix
和
data.frame
之间差异的重要性所在。请注意,HTML标签已保留。
class(x) <- NULL
dim(x)
class(x)
当
class(yz) <- NULL
dim(yz)
class(yz)
请注意,
x
成为一个包含不同元素(如向量和属性)的
list
,而
matrix
保持其原始结构,这要归功于其
dim
属性,因此
class
函数仍然可以识别它是一个矩阵,而
x
则完全变形,
class
无法处理它。
如果您想了解
class
的工作原理以及发生了什么,请参见我的回答
here
无论如何,虽然这仍然有效。
STATS <- colMeans(yz)
class(yz) <- NULL
dims <- dim(yz)
perm <- c(2L, seq_along(dims)[-2L])
array(STATS, dims[perm])
这会返回之前看到的错误。
x <- as.data.frame(yz)
STATS <- colMeans(x)
class(x) <- NULL
dims <- dim(x)
perm <- c(2L, seq_along(dims)[-2L])
array(STATS, dims[perm])
我将让您愉快地深入挖掘兔子洞,以更好地了解dim
的工作原理。
因此,在这里总结一下(正如@joran的评论中所提到的)- 请始终先阅读文档。如果您仔细查看?ar.ols
,则x
应为单变量或多元时间序列。在示例中,x
始终是类ts
的对象,永远不是data.frame
。
因此,虽然我同意对于这种特定情况,当您指定demean = FALSE
时,此错误本不应发生,但了解自己正在做什么仍然是更好的实践方法。换句话说,这是典型的XY问题类型的问题。
ar.ols
的数据有关。这段代码对我来说似乎有点奇怪,但我的一般建议是,由于ar.ols
的文档说它应该传递一个时间序列,所以你应该传递一个时间序列对象。 - joran?ts
。我不认为数据框与时间序列函数兼容。矩阵或时间序列对象是正确的选择。 - joran