R中的周和年季节性

3

我有从2007年1月1日到2016年12月31日的每日电力负载数据。 我使用ts()函数来加载数据,如下所示:

ts_load <- ts(data, start = c(2007,1), end = c(2016,12),frequency = 365)

我想从我的数据中去除年度和周度季节性,为了分解数据并去除季节性,我使用以下代码

decompose_load = decompose(ts_load, "additive")
deseasonalized = ts_load - decompose_load$seasonal

我的问题是,我这样做对吗?这是消除年度季节性的正确方法吗?消除周度季节性的正确方法是什么?


请使用 dput(head(data)) 包含实际数据,以便我们帮助您。 - morgan121
@dput(head(ts_load)) c(94275, 97269, 98686, 98262, 96839, 97398) - Mohab Mostafa
2
请将数据添加到您的原始评论中。参见:如何创建一个优秀的R可重现示例 - Roman
2个回答

3
几点说明:
  • ts系列必须具有定期间隔的点,并且每个周期中点的数量相同。在问题中指定了365的频率,但是一些年份(即闰年)将有366个点。特别地,如果您想要频率为一年,则不能使用未经调整的日常或每周数据,因为不同的年份具有不同的天数,并且一年中的周数不是整数。

  • decompose无法处理多个季节性。如果按星期计算,则意味着消除星期一,星期二等的影响;如果按年计算,则意味着消除每年1月1日、2日等的影响,则需要处理多个季节性。

  • end=c(2017,12)表示由于频率为365,因此为2017年的第12天。

forecast包中的msts函数可以处理多个和非整数季节性。

在基础R中,另一种方法是通过线性模型近似它,避免所有上述问题(但忽略相关性),我们将讨论这一点。

假设数据在本文结尾的注释中可重复显示,我们定义星期几(dow)和一年中的日期(doy)变量,并对其进行截距和趋势回归,然后在代码的最后一行构造仅截距加趋势加残差以去除季节性。这不是绝对必要的,但我们已经使用了scale来删除趋势的平均值,以便定义data.ds的三个术语是相互正交的——无论我们是否这样做,第三个术语都将根据线性模型的属性与其他2个术语正交。

trend <- scale(seq_along(d), TRUE, FALSE)
dow <- format(d, "%a")
doy <- format(d, "%j")
fm <- lm(data ~ trend + dow + doy)
data.ds <- coef(fm)[1] + coef(fm)[2] * trend + resid(fm)

注意

用于可重复形式的测试数据:

set.seed(123)
d <- seq(as.Date("2007-01-01"), as.Date("2016-12-31"), "day")
n <- length(d)
trend <- 1:n
seas_week <- rep(1:7, length = n)
seas_year <- rep(1:365, length = n)
noise <- rnorm(n)
data <- trend + seas_week + seas_year + noise

0

您可以使用dsa包中的dsa函数来调整每日时间序列。与回归解决方案相比,其优点在于考虑到季节影响随时间变化的情况,这通常是实际情况。 为了使用该函数,您的数据应该采用xts格式(来自xts包)。因为在这种情况下,闰年不会被忽略。 代码将类似于以下内容:

install.packages(c("xts", "dsa"))

data = rnorm(365.25*10, 100, 1)
data_xts <- xts::xts(data, seq.Date(as.Date("2007-01-01"), by="days", length.out = length(data)))

sa = dsa::dsa(data_xts, fourier_number = 24) 
# the fourier_number is used to model monthly recurring seasonal patterns in the regARIMA part

data_adjusted <- sa$output[,1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接