R 使用bfast检测季节性成分的变化

R 使用bfast检测季节性成分的变化,r,time-series,decomposition,R,Time Series,Decomposition,bfast包中的bfast()函数应该能够检测长期趋势中的断点和季节性成分的变化。一个例子是这个图(): 在这张图中,第2子地块显示了检测到的季节性变化,而第3子地块显示了趋势中的断点 然而,我不明白如何告诉bfast()寻找季节性变化/断点。我得到的只是长期趋势中的断点。这里是一个可复制的示例,模拟50年时间序列,每周测量季节变量y(即每年52次测量): [ 季节性的突然变化应该很容易检测到。但是,当我运行'bfast()时,它没有检测到任何变化: y_ts <- ts(mydata$

bfast包中的
bfast()
函数应该能够检测长期趋势中的断点和季节性成分的变化。一个例子是这个图():

在这张图中,第2子地块显示了检测到的季节性变化,而第3子地块显示了趋势中的断点

然而,我不明白如何告诉
bfast()
寻找季节性变化/断点。我得到的只是长期趋势中的断点。这里是一个可复制的示例,模拟50年时间序列,每周测量季节变量
y
(即每年52次测量):

[

季节性的突然变化应该很容易检测到。但是,当我运行'bfast()时,它没有检测到任何变化:

y_ts <- ts(mydata$y_shifted, start = c(1,1), frequency = freq)
fit <- bfast(y_ts, h=.15, season="harmonic", max.iter=20, breaks=3)
plot(fit)

y_ts我在对我的消费者投资组合数据进行
bfast
测试时遇到了同样的问题,但没有找到任何真正的解决方案。我继续深入研究地球感应社区的bfast文献,这是bfast
最早开发和广泛使用的地方。我的理解是,要获得b快速始终适合一个有用的季节性组件

几天前,我在上遇到了这个Quora讨论,发现有一个新的R包用于断点检测和时间序列分解。还有一条很好的推文显示了快速比较

经过一些实验,我发现
Rbeast
能够在我的数据和你的数据中找出季节性断点。坦率地说,我不知道
Rbeast
是如何工作的。
Rbeast
中的BEAST算法似乎相当复杂,有大量的输出;它没有很好的文档记录,也不像bfast那么容易使用。让我来看看展示我得到的,首先使用你的数据,然后使用第二个人工时间序列

你的数据 下图显示,趋势基本上是一个零常数,在趋势中找到断点(即Rbeast中使用的转换点)的概率也几乎为零



第二个时间序列 Rbeast的一个很酷的特性是对调和季节模型的正弦/余弦阶的估计。下面我生成了一个时间序列,该时间序列在季节分量中有三个分段(即两个分段)加上一个没有分段的倾斜趋势。这三个季节分段具有不同的正弦阶,分别取1、2和3

# Generate a sample time series with three seasonal segments
# the sin/cos orders for the three segs are different.
seg1 <- 1:1000
seg2 <- 1001:2000
seg3 <- 2001:3000
new_data <- c( sin(seg1*2*pi/52), 0.6*sin( seg2*2*pi/52*2), 0.3*sin( seg3*2*pi/52*3)) + (1:3000)*0.0002+ rnorm(3000, sd = 0.1)

以上是Rbeast结果。两次中断和三次季节性分段得到恢复。同样,趋势中没有中断。趋势的断点概率显示可能存在一些断点,但概率曲线实际上接近于零,并且没有在正常y范围内绘制

设置“opt$ComputeHarmonicRecorder”告诉beast保存估计的季节性和声顺序以适应$horder。下图是输出。三个sin顺序也恢复得很好。此曲线还显示了两个季节性休息的位置

plot(fit$horder,type='l')

y_ts <- ts(mydata$y_shifted, start = c(1,1), frequency = freq)
fit <- bfast(y_ts, h=.15, season="harmonic", max.iter=20, breaks=3)
plot(fit)
mydata$Residuals <- fit$output[[1]]$Nt
ggplot(mydata, aes(Week, Residuals, group = Year, color = Phase)) + geom_point()
# The original code to generate your data
n_years <- 50
freq    <- 52
y_pattern <- sin(seq(0, 2*pi, length = freq))
y         <- rep(y_pattern, n_years) + rnorm(freq*n_years, sd = 0.1)
mydata    <- data.frame(Year = rep(1:n_years, each = freq), Week = rep(1:freq, n_years), y) 

move_data <- function(data, year, weeks_to_move){
  x <- data[data$Year == year, "y"]
  c(x[seq(52 - weeks_to_move + 1,52)], x[seq(1, 52 - weeks_to_move)])
}

mydata$y_shifted <- mydata$y
for (year in 26:50){
  mydata$y_shifted[mydata$Year == year] <- move_data(mydata, year, weeks_to_move = 8)
}

# You data analyzed by the BEAST algorithm in Rbeast
library(Rbeast) 
# Rbeast's input should be a data vector not a ts object.
# '52' is the frequency (called period in BEAST)
fit <- beast(mydata$y_shifted,52)
plot(fit)

# another way to run BEAST by customizing the parameters explicitly
opt$period=52         # ts frequency/period
opt$minSeasonOrder=1  # min harmonic order used to fit seasonal cmpnt
opt$maxSeasonOrder=5  # max harmonic order used to fit seasonal cmpnt
fit <- beast(mydata$y_shifted,opt)
plot(fit)
par( mar = c(3, 5, 3, 2), mfrow=c(2,1) )
plot( fit$t,  main='trend',  type='l', ylim=c(-0.1,0.1) )
plot( fit$tProb,main='changepoint probability in trend',type='l', ylim=c(0,1) )
# Generate a sample time series with three seasonal segments
# the sin/cos orders for the three segs are different.
seg1 <- 1:1000
seg2 <- 1001:2000
seg3 <- 2001:3000
new_data <- c( sin(seg1*2*pi/52), 0.6*sin( seg2*2*pi/52*2), 0.3*sin( seg3*2*pi/52*3)) + (1:3000)*0.0002+ rnorm(3000, sd = 0.1)
# Test bfast using new_data
y_ts <- ts(new_data, start = c(1,1), frequency = 52)
fit  <- bfast(y_ts, h=.15, season="harmonic", max.iter=20, breaks=3)
plot(fit)
# Analyze the new_data time series using Rbeast

opt=list()
opt$period=52
opt$minSeasonOrder=1
opt$maxSeasonOrder=4
opt$samples = 6000  
opt$computeHarmonicOrder = 1 # "1" asks BEAST to output seasonal order
fit <- beast(new_data ,opt)
plot(fit)
plot(fit$horder,type='l')