到目前为止,当我要预测多个时间序列时,我正在使用Hyndman教授的this方法。但是当我有大量的ts时,它就相当慢。
现在我正尝试使用apply()
函数,如下所示
library(forecast)
fc_func <- function(y){
forecast(auto.arima(y),h=12)$mean
}
retail <- read.csv("https://robjhyndman.com/data/ausretail.csv",header=FALSE)
retail <- ts(retail[,-1],f=12,s=1982+3/12)
frc<- apply(retail,2 ,fc_func)
似乎运行良好,但是当我使用for
循环时,如下所示:
ns <- ncol(retail)
h <- 12
fcast <- matrix(NA,nrow=h,ncol=ns)
for(i in 1:ns){
fcast[,i] <- forecast(auto.arima(retail[,i]),h=h)$mean
}
我得到了不同的预测点。是什么原因?
编辑:我通过更改“ fc_func”功能对其进行了修复。现在它返回与for
循环相同的结果,但现在它也和for
循环一样慢
fc_func <- function(x){
ts(x,f=12,s=1982+3/12)->y
forecast(auto.arima(y),h=12)$mean
}
retail <- read.csv("https://robjhyndman.com/data/ausretail.csv",header=FALSE)
retail <- ts(retail[,-1],f=12,s=1982+3/12)
frc<- apply(retail,2 ,fc_func)
答案 0 :(得分:1)
为了调试,我在应用中添加了一些打印件。有趣的是班级(y)
library(forecast)
fc_func <- function(y){
print(length(y))
print(class(y))
#print(y)
forecast(auto.arima(y),h=12)$mean
}
retail <- read.csv("https://robjhyndman.com/data/ausretail.csv",header=FALSE)
retail <- ts(retail[,-1],f=12,s=1982+3/12)
retail2 = retail
#retail = retail2[1:333,1:42]
frc<- apply(retail,2 ,fc_func)
所有y均以数字形式到达。
> frc<- apply(retail,2 ,fc_func)
[1] 333
[1] "numeric"
[1] 333
[1] "numeric"
[1] 333
[1] "numeric"
[1] 333
[1] "numeric"
[1] 333
在for循环中这是不同的:
ns <- ncol(retail)
h <- 12
fcast1 <- matrix(NA,nrow=h,ncol=ns)
for(i in 1:ns){
print(length(retail[,i]))
print(class(retail[,i]))
#print(retail[,i])
fcast1[,i] <- forecast(auto.arima(retail[,i]),h=h)$mean
}
此处,变量作为ts传递到auto.arima。
> for(i in 1:ns){
+ print(length(retail[,i]))
+ print(class(retail[,i]))
+ #print(retail[,i])
+ fcast1[,i] <- forecast(auto.arima(retail[,i]),h=h)$mean
+ }
[1] 333
[1] "ts"
[1] 333
[1] "ts"
[1] 333
[1] "ts"
[1] 333
我想这会造成差异,因为当我将零售量减少为一个简单矩阵时,
retail = retail[1:NROW(retail), 1:NCOL(retail)]
再次运行for循环,我得到的结果与Apply版本完全相同。
all.equal(frc, fcast1)
因此,我想您必须先将fc_func中的变量转换为ts,然后再将其发送到预测函数中。
作为一种解决方法(并且因为我不知道如何将y转换为所需的ts对象),您可以使用一个sapply版本:
fc_func2 <- function(y){
forecast(auto.arima(retail[,y]),h=12)$mean
}
frc2 <- sapply(1:NCOL(retail), fc_func2)
它应该提供所需的值,但不确定是否比循环版本更快。
答案 1 :(得分:1)
问题是apply()
处理time series
对象 retail 的类。作为{em> apply 系列的基本版本,apply()
最适合用于简单矩阵对象。它将在调用时将其输入转换为带有as.matrix()
的矩阵对象,因此为什么经常警告apply()
不能用于数据帧。
根据?apply
文档:
如果X不是数组,而是具有非null暗淡的类的对象 值(例如数据框),尝试将其强制转换为数组 通过as.matrix(如果它是二维的)(例如,数据帧),或者通过 as.array
因此apply
在处理为fc_func
之前不会保留其输入的类对象:
class(retail)
# [1] "mts" "ts" "matrix"
使用sapply
运行速度与for
一样慢的dimnames
并移除for
时返回的结果与# LOOP VERSION
ns <- ncol(retail)
h <- 12
fcast1 <- matrix(NA,nrow=h,ncol=ns)
for(i in 1:ns) {
fcast1[,i] <- forecast(auto.arima(retail[,i]), h=h)$mean
}
# SAPPLY VERSION
frc_test <- sapply(retail, fc_func, USE.NAMES = FALSE)
dimnames(frc_test) <- NULL
identical(frc_test, fcast1)
# [1] TRUE
循环完全相同:
Date----------- count
06-01-2017 18.51 1
06-01-2017 19.11 10
20-01-2017 19.55 20
21-01-2017 20.10 30
22-01-2017 20.10 40
23-01-2017 20.10 50
23-01-2017 20.10 60
29-01-2017 21.33 70