Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >用R语言做时间序列分析(附数据集和源码)

用R语言做时间序列分析(附数据集和源码)

作者头像
机器学习AI算法工程
发布于 2018-03-13 07:55:10
发布于 2018-03-13 07:55:10
6K10
代码可运行
举报
运行总次数:0
代码可运行

时间序列(time series)是一系列有序的数据。通常是等时间间隔的采样数据。如果不是等间隔,则一般会标注每个数据点的时间刻度。

下面以time series 普遍使用的数据 airline passenger为例。 这是十一年的每月乘客数量,单位是千人次。

如果想尝试其他的数据集,可以访问这里: https://datamarket.com/data/list/?q=provider:tsdl

可以很明显的看出,airline passenger的数据是很有规律的。

time series data mining 主要包括decompose(分析数据的各个成分,例如趋势,周期性),prediction(预测未来的值),classification(对有序数据序列的feature提取与分类),clustering(相似数列聚类)等。

这篇文章主要讨论prediction(forecast,预测)问题。 即已知历史的数据,如何准确预测未来的数据。

先从简单的方法说起。给定一个时间序列,要预测下一个的值是多少,最简单的思路是什么呢?

(1)mean(平均值):未来值是历史值的平均。

(2)exponential smoothing (指数衰减):当去平均值得时候,每个历史点的权值可以不一样。最自然的就是越近的点赋予越大的权重。

或者,更方便的写法,用变量头上加个尖角表示估计值

(3) snaive : 假设已知数据的周期,那么就用前一个周期对应的时刻作为下一个周期对应时刻的预测值

(4) drift:飘移,即用最后一个点的值加上数据的平均趋势

介绍完最简单的算法,下面开始介绍两个time series里面最火的两个强大的算法: Holt-Winters 和 ARIMA。 上面简答的算法都是这两个算法的某种特例。

(5)Holt-Winters: 三阶指数平滑

Holt-Winters的思想是把数据分解成三个成分:平均水平(level),趋势(trend),周期性(seasonality)。R里面一个简单的函数stl就可以把原始数据进行分解:

一阶Holt—Winters假设数据是stationary的(静态分布),即是普通的指数平滑。二阶算法假设数据有一个趋势,这个趋势可以是加性的(additive,线性趋势),也可以是乘性的(multiplicative,非线性趋势),只是公式里面一个小小的不同而已。 三阶算法在二阶的假设基础上,多了一个周期性的成分。同样这个周期性成分可以是additive和multiplicative的。 举个例子,如果每个二月的人数都比往年增加1000人,这就是additive;如果每个二月的人数都比往年增加120%,那么就是multiplicative。

R里面有Holt-Winters的实现,现在就可以用它来试试效果了。我用前十年的数据去预测最后一年的数据。 性能衡量采用的是RMSE。 当然也可以采用别的metrics:

预测结果如下:

结果还是很不错的。

(6) ARIMA: AutoRegressive Integrated Moving Average

ARIMA是两个算法的结合:AR和MA。其公式如下:

是白噪声,均值为0, C是常数。 ARIMA的前半部分就是Autoregressive:

, 后半部分是moving average:

。 AR实际上就是一个无限脉冲响应滤波器(infinite impulse resopnse), MA是一个有限脉冲响应(finite impulse resopnse),输入是白噪声。

ARIMA里面的I指Integrated(差分)。 ARIMA(p,d,q)就表示p阶AR,d次差分,q阶MA。 为什么要进行差分呢? ARIMA的前提是数据是stationary的,也就是说统计特性(mean,variance,correlation等)不会随着时间窗口的不同而变化。用数学表示就是联合分布相同:

当然很多时候并不符合这个要求,例如这里的airline passenger数据。有很多方式对原始数据进行变换可以使之stationary:

(1) 差分,即Integrated。 例如一阶差分是把原数列每一项减去前一项的值。二阶差分是一阶差分基础上再来一次差分。这是最推荐的做法

(2)先用某种函数大致拟合原始数据,再用ARIMA处理剩余量。例如,先用一条直线拟合airline passenger的趋势,于是原始数据就变成了每个数据点离这条直线的偏移。再用ARIMA去拟合这些偏移量。

(3)对原始数据取log或者开根号。这对variance不是常数的很有效。

如何看数据是不是stationary呢?这里就要用到两个很常用的量了: ACF(auto correlation function)和PACF(patial auto correlation function)。对于non-stationary的数据,ACF图不会趋向于0,或者趋向0的速度很慢。 下面是三张ACF图,分别对应原始数据,一阶差分原始数据,去除周期性的一阶差分数据:

确保stationary之后,下面就要确定p和q的值了。定这两个值还是要看ACF和PACF:

确定好p和q之后,就可以调用R里面的arime函数了。 值得一提的是,R里面有两个很强大的函数: ets 和 auto.arima。 用户什么都不需要做,这两个函数会自动挑选一个最恰当的算法去分析数据。

在R中各个算法的效果如下:

代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
passenger = read.csv('passenger.csv',header=F,sep=' ')
p<-unlist(passenger)
pt<-ts(p,frequency=12,start=2001)
plot(pt)
train<-window(pt,start=2001,end=2011+11/12)test<-window(pt,start=2012)

library(forecast)
pred_meanf<-meanf(train,h=12)
rmse(test,pred_meanf$mean) #226.2657pred_naive<-naive(train,h=12)
rmse(pred_naive$mean,test)#102.9765pred_snaive<-snaive(train,h=12)
rmse(pred_snaive$mean,test)#50.70832pred_rwf<-rwf(train,h=12, drift=T)
rmse(pred_rwf$mean,test)#92.66636pred_ses <- ses(train,h=12,initial='simple',alpha=0.2)
rmse(pred_ses$mean,test) #89.77035pred_holt<-holt(train,h=12,damped=F,initial="simple",beta=0.65)
rmse(pred_holt$mean,test)#76.86677  without beta=0.65 it would be 84.41239pred_hw<-hw(train,h=12,seasonal='multiplicative')
rmse(pred_hw$mean,test)#16.36156fit<-ets(train)
accuracy(predict(fit,12),test) #24.390252pred_stlf<-stlf(train)
rmse(pred_stlf$mean,test)#22.07215plot(stl(train,s.window="periodic"))  #Seasonal Decomposition of Time Series by Loess

fit<-auto.arima(train)
accuracy(forecast(fit,h=12),test) #23.538735ma = arima(train, order = c(0, 1, 3),   seasonal=list(order=c(0,1,3), period=12))
p<-predict(ma,12)
accuracy(p$pred,test)  #18.55567BT = Box.test(ma$residuals, lag=30, type = "Ljung-Box", fitdf=2)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据挖掘DT数据分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
6666666666666666666666666
6666666666666666666666666
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
【C++高阶】二叉搜索树的全面解析与高效实现
二叉搜索树(BST,Binary Search Tree)又称二叉排序树,是一种特殊的二叉树,它或者是一棵空树,或者是具有以下性质的二叉树:
IsLand1314
2024/10/15
1400
【C++高阶】二叉搜索树的全面解析与高效实现
【探寻C++之旅】第九章:二叉搜索树
二叉搜索树是一棵特殊的二叉树,从名字上我们可以看出这颗特殊的二叉树的特殊点就在于搜索二字。接下来我们先了解一下什么是二叉搜索树,再看一看二叉搜索有什么作用。
code_monnkey_
2025/05/31
830
【探寻C++之旅】第九章:二叉搜索树
C++:二叉搜索树
二叉搜索树(BST, Binary Search Tree)又叫做二叉排序树,它可以是一颗空树,其性质如下:
二肥是只大懒蓝猫
2023/03/30
2880
C++:二叉搜索树
C++二叉搜索树与KV模型
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值 它的左右子树也分别为二叉搜索树
有礼貌的灰绅士
2023/04/12
4220
C++二叉搜索树与KV模型
【C++】二叉搜索树 - 从基础概念到代码实现
最优情况下,二叉搜索树为完全二叉树(或者接近完全二叉树),其高度为:log2 N 最差情况下,二叉搜索树退化为单指树,其高度为:N 所以综合而言二叉搜索树增删查改的时间复杂度为:O(N)
_孙同学
2025/04/27
1330
【C++】二叉搜索树 - 从基础概念到代码实现
【数据结构与算法】AVL二叉搜索树的CRUD实现与应用详解
二叉搜索树(Binary Search Tree)又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
利刃大大
2025/02/03
660
【数据结构与算法】AVL二叉搜索树的CRUD实现与应用详解
C++进阶:二叉搜索树介绍、模拟实现(递归迭代两版本)及其应用
假设我们插入以下元素:5, 3, 7, 1, 4, 6, 8,可以构建如下的二叉搜索树(BST):
是Nero哦
2024/03/21
2740
C++进阶:二叉搜索树介绍、模拟实现(递归迭代两版本)及其应用
二叉搜索树实现教程:用C++实现数据存储与查找
最优情况下,⼆叉搜索树为完全⼆叉树(或者接近完全⼆叉树),其⾼度为:O(log2N) 最差情况下,⼆叉搜索树退化为单支树(或者类似单⽀),其⾼度为:O(N /2) 所以综合而言⼆叉搜索树增删查改时间复杂度为:O(N) 那么这样的效率显然是无法满⾜我们需求的,在后续当中还有平衡⼆叉搜索树AVL树和红⿊树,才能适用于我们在内存中存储和搜索数据。
用户11286421
2024/11/21
1120
二叉搜索树实现教程:用C++实现数据存储与查找
【C++】从零开始构建二叉搜索树
普通的二叉树没有特别的性质,今天我们就来赋予其一个全新的性质来满足高速搜索的需求 ,并为后序的map与set做铺垫 ,二叉搜索树的特性了解,有助于更好的理解map和set的特性
叫我龙翔
2024/05/26
1380
【C++】从零开始构建二叉搜索树
二叉搜索树模拟实现
二叉搜索树(BST,Binary Search Tree)又称二叉排序树,二叉查找树,主要功能是排序,去重,查找一个值是否存在。
咬咬
2024/06/12
970
二叉搜索树模拟实现
【C++深度探索】二叉搜索树的全面解析与高效实现
二叉搜索树(BST,Binary Search Tree)又称二叉排序树,是一种特殊的二叉树,它或者是一棵空树,或者是具有以下性质的二叉树:
大耳朵土土垚
2024/07/25
1410
【C++深度探索】二叉搜索树的全面解析与高效实现
【C++】二叉搜索树
1. 搜索树的结点的定义也比较简单,每个结点都有左右子树和自身存储的_key值,_key就是利用搜索树进行搜索时的数据。
举杯邀明月
2023/04/12
2950
【C++】二叉搜索树
【C++】二叉搜索树
https://blog.csdn.net/hsy1603914691/article/details/146592632
风中的云彩
2025/04/11
1060
【C++】二叉搜索树
【C++】————搜索二叉树
建立一颗二叉搜索树一般有下面几个步骤,首先我们要建立一颗空树,然后不断的去插入节点,前面我们说过对于一颗二叉搜索树,小于节点对应的值放在左边,大于节点对应的值放在右边。
用户11036582
2024/08/06
860
【C++】————搜索二叉树
二叉搜索树
二叉搜索树是在普通的二叉树上进阶的,所以咱们今天的内容也可以说是,数据结构二叉树的进阶。二叉搜索树可谓是起到了承上启下的作用,向前承接了数据结构的二叉树,向后对于map和set的模拟实现也起到了启示作用。
小灵蛇
2024/06/06
1010
二叉搜索树
【数据结构】二叉搜索树BSTree
(注意:不能插入重复的元素,并且每次插入都是要定位到空节点的位置;我们先定义一个 cur从root开始,比较元素的大小:若插入的元素比当前位置元素小就往左走,比当前位置元素大就往右走,直到为空,相等就不能插入了;同时定义一个parent去记录当前 cur的前一个位置,最后判断cur是parent的左子树还是右子树即可)
平凡的人1
2023/10/15
2660
【数据结构】二叉搜索树BSTree
【c++】二叉搜索树(BST)
每个节点有两个指针,分别指向它的左子节点和右子节点。如果子节点不存在,则这些指针为nullptr
用户11029103
2024/05/24
1100
【c++】二叉搜索树(BST)
【C++】二叉搜索树(概念、操作)
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情 况:
秦jh
2024/07/19
1420
【C++】二叉搜索树(概念、操作)
【C++】二叉搜索树
从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。 最多查找高度次,走到到空,还没找到,这个值不存在
lovevivi
2023/10/16
1820
【C++】二叉搜索树
【数据结构】二叉搜索树
在数据结构专栏,笔者介绍了,单纯的二叉树实际意义并不大,但是单二叉树变成平衡二叉搜索树就会很有用,那么本文就先来介绍一下什么是二叉搜索树。
ZLRRLZ
2025/01/20
1080
【数据结构】二叉搜索树
推荐阅读
相关推荐
【C++高阶】二叉搜索树的全面解析与高效实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验