90-预测分析-R语言实现-时间序列1

时间序列(time series)是随机变量Y1、Y2、……Yt的一个序列,它是由等距的时间点序列索引的。
一个时间序列的均值函数就是该时间序列在某个时间索引t上的期望值。一般情况下,某个时间序列在某个时间索引t1的均值并不等于该时间序列在另一个不同的时间索引t2的均值。
自协方差函数及自相关函数是衡量构成时间序列的随机变量在不同时间点上相互线性依赖性的两个重要函数。自相关函数通常缩略为ACF函数。ACF函数是对称的,但是无单位,其绝对值被数值1约束,即当两个时间序列索引之间的自相关度是1或-1,就代表两者之间存在完全线性依赖或相关,而当相关度是0时,就代表完全线性无关。
平稳性:实质描述的是一个时间序列的概率表现不会随着时间的流逝而改变。常用的平稳性的性质有严格平稳和弱平稳两个版本。tseries包的adf.test()函数可以检验时间序列的平稳性,返回的p值小于0.05则表示是平稳的。
白噪声是一个平稳过程,因为它的均值和方差都是常数。
随机漫步的均值是常数(不带漂移的随机漫步),但它的方差是随着时间的变化而不同的,因此它是不平稳的。
自回归模型(Autoregressive models, AR)来源于要让一个简单模型根据过去有限窗口时间里的最近值来解释某个时间序列当前值的想法。
自回归条件异方差模型:ARIMA模型的关键前提条件是,虽然序列本身是非平稳的,但是我们可以运用某个变换来获得一个平稳的序列。像这样为非平稳时间序列构建模型的方法之一是作出一个假设,假设该模型非平稳的原因是该模型的方差会以一种可预见的方式随时间变化,这样就可以把方差随时间的变化建模为一个自回归过程,这种模型被称为自回归条件异方差模型(ARCH)。加入了移动平均方差成分的ARCH模型称为广义自回归条件异方差模型(GARCH)。

任务:预测强烈地震
数据集:2000-2008年期间在希腊发生的强度大于里氏4.0级地震的时间序列。

> library(pacman)
> p_load(dplyr, RCurl)

1、数据准备

> url <- "http://www.geophysics.geol.uoa.gr/catalog/catgr_20002008.epi"
> # 从网络获取数据,设置列名,并按空格分割为多列
> seismic <- getURL(url = url) %>%
+   readr::read_csv(col_names = F) %>%
+   setNames("value") %>% 
+   tidyr::separate(col = "value",
+                   into = c("year", "mo", "day", "hr", "mn", "sec", "lat", 
+                            "long", "depth", "mw"),
+                   sep = "[[:space:]]+")
> 
> str(seismic)
## tibble [3,823 × 10] (S3: tbl_df/tbl/data.frame)
##  $ year : chr [1:3823] "2000" "2000" "2000" "2000" ...
##  $ mo   : chr [1:3823] "1" "1" "1" "1" ...
##  $ day  : chr [1:3823] "1" "1" "2" "2" ...
##  $ hr   : chr [1:3823] "1" "4" "10" "18" ...
##  $ mn   : chr [1:3823] "19" "2" "44" "48" ...
##  $ sec  : chr [1:3823] "28.30" "28.40" "10.90" "55.60" ...
##  $ lat  : chr [1:3823] "41.950N" "35.540N" "35.850N" "35.480N" ...
##  $ long : chr [1:3823] "20.630E" "22.760E" "27.610E" "22.510E" ...
##  $ depth: chr [1:3823] "5.0" "22.0" "3.0" "32.0" ...
##  $ mw   : chr [1:3823] "4.8" "3.7" "3.7" "4.0" ...
> DataExplorer::profile_missing(seismic)
## # A tibble: 10 x 3
##    feature num_missing pct_missing
##    <fct>         <int>       <dbl>
##  1 year              0           0
##  2 mo                0           0
##  3 day               0           0
##  4 hr                0           0
##  5 mn                0           0
##  6 sec               0           0
##  7 lat               0           0
##  8 long              0           0
##  9 depth             0           0
## 10 mw                0           0

不存在缺失值。
将经度和纬度之外的变量转换为数值型。

> seismic <- seismic %>% 
+   mutate(across(-c(lat, long), .fns = as.numeric))
> str(seismic)
## tibble [3,823 × 10] (S3: tbl_df/tbl/data.frame)
##  $ year : num [1:3823] 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 ...
##  $ mo   : num [1:3823] 1 1 1 1 1 1 1 1 1 1 ...
##  $ day  : num [1:3823] 1 1 2 2 6 7 7 10 11 12 ...
##  $ hr   : num [1:3823] 1 4 10 18 15 4 9 2 7 2 ...
##  $ mn   : num [1:3823] 19 2 44 48 51 9 36 48 44 14 ...
##  $ sec  : num [1:3823] 28.3 28.4 10.9 55.6 12.4 40.5 36.5 15.6 58.4 2.8 ...
##  $ lat  : chr [1:3823] "41.950N" "35.540N" "35.850N" "35.480N" ...
##  $ long : chr [1:3823] "20.630E" "22.760E" "27.610E" "22.510E" ...
##  $ depth: num [1:3823] 5 22 3 32 5 6 10 5 29 36 ...
##  $ mw   : num [1:3823] 4.8 3.7 3.7 4 4 3.9 3.7 3.7 4.1 3.7 ...

2、数据处理

> # 地震按年分月度计数
> num <- seismic %>% 
+   group_by(year, mo) %>% 
+   summarise(num = n())
> 
> summary(seismic)
##       year            mo              day              hr              mn             sec       
##  Min.   :2000   Min.   : 1.000   Min.   : 1.00   Min.   : 0.00   Min.   : 0.00   Min.   : 0.00  
##  1st Qu.:2001   1st Qu.: 4.000   1st Qu.: 9.00   1st Qu.: 5.00   1st Qu.:15.00   1st Qu.:15.60  
##  Median :2003   Median : 7.000   Median :16.00   Median :12.00   Median :29.00   Median :30.20  
##  Mean   :2004   Mean   : 6.613   Mean   :16.03   Mean   :11.63   Mean   :29.38   Mean   :30.25  
##  3rd Qu.:2006   3rd Qu.: 9.000   3rd Qu.:24.00   3rd Qu.:18.00   3rd Qu.:44.00   3rd Qu.:45.00  
##  Max.   :2008   Max.   :12.000   Max.   :31.00   Max.   :23.00   Max.   :59.00   Max.   :60.00  
##      lat                long               depth              mw       
##  Length:3823        Length:3823        Min.   :  2.00   Min.   :3.700  
##  Class :character   Class :character   1st Qu.:  6.00   1st Qu.:3.700  
##  Mode  :character   Mode  :character   Median : 17.00   Median :3.800  
##                                        Mean   : 20.41   Mean   :3.938  
##                                        3rd Qu.: 27.00   3rd Qu.:4.000  
##                                        Max.   :181.00   Max.   :6.400
> # 按月读数,创建时间序列
> seismic_ts <- ts(num$num, start = c(2000, 1), end = c(2008, 1), frequency = 12)
> 
> plot.ts(seismic_ts)
月度计数时间序列

从图上可以看出,数据在30次左右波动,并且不存在总体向上的趋势。

3、建模

通过尝试多个不同的组合来找到最优的阶数参数p,d,q,确定最优的准则是使用参数建模,能使模型的AIC值最小。

> ngrid <- expand.grid(d = 0:2, p = 0:6, q = 0:6)
> head(ngrid)
##   d p q
## 1 0 0 0
## 2 1 0 0
## 3 2 0 0
## 4 0 1 0
## 5 1 1 0
## 6 2 1 0

定义一个函数,它会针对某个阶数参数拟合出一个ARIMA模型,并返回模型的AIC值。如果某组参数导致模型无法收敛,就会产生错误,并且无法返回AIC,这时需要人为设置其AIC为无限大(InF)。

> get_aic <- function(data, p, d, q) {
+   res <- tryCatch({
+     model <- arima(data, order = c(p, d, q))
+     return(model$aic)
+   }, error = function(e) {
+     return(Inf)
+   })
+ }

调用函数,选取最合适的模型。

> ngrid$aic <- mapply(FUN = function(x, y, z) {
+   get_aic(seismic_ts, x, y, z)}, ngrid$p, ngrid$d, ngrid$q)

然后找出最优的阶数参数:

> filter(ngrid, aic == min(aic))
##   d p q     aic
## 1 1 1 1 832.171

得到最合适的模型为ARIMA(1, 1, 1)。再次使用最优参数训练模型。

> fit.arima <- arima(seismic_ts, order = c(1, 1, 1))
> fit.arima
## 
## Call:
## arima(x = seismic_ts, order = c(1, 1, 1))
## 
## Coefficients:
##          ar1      ma1
##       0.2949  -1.0000
## s.e.  0.0986   0.0536
## 
## sigma^2 estimated as 306.9:  log likelihood = -413.09,  aic = 832.17

4、预测

使用forecast包预测未来值。

> hat <- forecast::forecast(fit.arima, 10)
> plot(hat)
预测

带颜色的条带是预测的置信区间,蓝色线表示均值,结果表示在后续的10个月里,地震的数量会有小幅增加。
检查自相关函数:

> acf(seismic_ts)
自相关函数

ACF绘图:虚线显示了一个95%的置信区间,特定延迟对应的ACF函数值如果处于该区间内,就不会被认为具有统计显著性(大于0)。这个ACF轮廓表明,针对本数据集,简单的AR(1)过程可能是一种合适的拟合方式。
PACF为偏自相关函数,是将时间延迟K的PACF定义为在消除了小于K的延迟中存在的任何相关性影响的情况下所产生的相关性。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269