时间序列基础包(zoo,zooreg)

参考: 《R的极客理想——工具篇》

zoo包介绍

zoo是一个R语言类库,zoo类库中定义了一个名为zoo的S3类型对象,用于描述规则的和不规则的有序的时间序列数据。zoo对象是一个独立的对象,包括索引、日期、时间,只依赖于基础的R环境。zooreg对象继承了zoo对象,只能用于规则的时间序列数据。R语言中很多其他的程序包,都是以zoo和zooreg作为时间序列数据的基础的!zoo包的API主要有6类.

基础对象

zoo: 有序的时间序列对象。

zooreg: 规则的时间序列对象,继承zoo对象。与zoo相比,不同之处在于zooreg要求数据是连续的。

类型转换

as.zoo: 把一个对象转型为zoo类型。

plot.zoo: 为plot函数提供zoo的接口。

xyplot.zoo: 为lattice的xyplot函数提供zoo的接口。

ggplot2.zoo: 为ggplot2包提供zoo的接口。

数据操作

coredata: 查看或编辑zoo的数据部分。

index: 查看或编辑zoo的索引部分。

window.zoo: 按时间过滤数据。

merge.zoo: 合并多个zoo对象。

read.zoo: 从文件读写zoo序列。

aggregate.zoo: 计算zoo数据。

rollapply: 对zoo数据的滚动处理。

rollmean: 对zoo数据的滚动计算均值。

NA值处理

na.fill: NA值的填充。

na.locf: 替换NA值。

na.aggregate: 计算统计值替换NA值。

na.approx: 计算插值替换NA值。

na.StructTS: 计算季节Kalman滤波替换NA值。

na.trim: 过滤有NA的记录。

辅助工具

is.regular: 检查是否是规则的序列。

lag.zoo: 计算步长和差分。

MATCH: 取交集。

ORDER: 值排序,输出索引。

显示控制

yearqtr: 以年季度显示时间。

yearmon: 以年月显示时间。

xblocks: 作图沿x轴分割图形。

make.par.list: 用于给plot.zoo 和 xyplot.zoo 数据格式转换。

使用

zoo对象

zoo对象包括两部分,即数据部分和索引部分。首先是函数定义:

zoo(x = NULL, order.by = index(x), frequency = NULL) 

其中x是数据部分,允许类型为向量、矩阵、因子;
order.by是索引部分,字段唯一性要求,用于排序;
frequency是每个时间单元显示的数量。

> x.Date <- as.Date("2003-02-01") + c(1, 3, 7, 9, 14) – 1  # 定义一个不连续的日期的向量  
> x.Date  
[1] "2003-02-01" "2003-02-03" "2003-02-07" "2003-02-09" "2003-02-14"  
> class(x.Date)  
[1] "Date"  

> x <- zoo(rnorm(5), x.Date)  # 定义不连续的zoo对象  
> x  
2003-02-01 2003-02-03 2003-02-07 2003-02-09 2003-02-14  
0.01964254 0.03122887 0.64721059 1.47397924 1.29109889  
> class(x)  
[1] "zoo"  

> plot(x)  # 画图显示 

这里写图片描述

接下来,我们以数字为索引创建多组时间序列。用如下代码,生成一个有12个元素的4行3列的矩阵,以数字0:10为索引,创建一个zoo类型对象y,并以图形输出y,产生的结果如图.

> y <- zoo(matrix(1:12, 4, 3),0:10)  
> y  
0  1 5  9  
1  2 6 10  
2  3 7 11  
3  4 8 12  
4  1 5  9  
5  2 6 10  
6  3 7 11  
7  4 8 12  
8  1 5  9  
9  2 6 10  
10 3 7 11  

> plot(y)  # 矩阵的每一列为一组时间序列图 

这里写图片描述

zooreg对象

函数定义:

zooreg(data, start = 1, end = numeric(), frequency = 1,  
deltat = 1, ts.eps = getOption("ts.eps"), order.by = NULL) 

下面是参数说明。

data: 数据部分,允许类型为向量、矩阵、因子。

start: 时间部分,开始时间。

end: 时间部分,结束时间。

frequency: 每个时间单元显示的数量。

deltat: 连续观测的采样周期,不能与frequency同时出现,例如,取每月的数据,为1/12。

ts.eps: 时间序列间隔,当数据时间间隔小于ts.eps时,使用ts.eps作为时间间隔。通过getOption(“ts.eps”)设置,默认是1e-05。

order.by: 索引部分,字段唯一性要求,用于排序, 继承zoo的order.by。

> zooreg(1:10, frequency = 4, start = c(1959, 2))  
1959(2) 1959(3) 1959(4) 1960(1) 1960(2) 1960(3) 1960(4) 1961(1) 1961(2) 1961(3)  
      1       2       3       4       5       6       7       8       9        10  

> as.zoo(ts(1:10, frequency = 4, start = c(1959, 2)))  
1959(2) 1959(3) 1959(4) 1960(1) 1960(2) 1960(3) 1960(4) 1961(1) 1961(2) 1961(3)  
      1       2       3       4       5       6       7       8       9        10  

> zr<-zooreg(rnorm(10), frequency = 4, start = c(1959, 2))  
> plot(zr) 

这里写图片描述

zoo对象与zooreg对象的区别

zoo对象与zooreg对象的区别体现在计算步长和差分方面。

lag(步长):zoo根据索引计算,zooreg根据值计算。

diff(差分):zoo根据索引计算,zooreg根据值计算。

例如,对同一组值不连续的数据(1, 2, 3, 6, 7, 8),二者的计算结果如下:

x <- c(1, 2, 3, 6, 7, 8)  
> zz <- zoo(x, x)  
> zr <- as.zooreg(zz)  

> lag(zz, k = -1)  # 计算步长  

2 3 6 7 8  
1 2 3 6 7  

> lag(zr, k = -1)  
2 3 4 7 8 9  
1 2 3 6 7 8  

> diff(zz)  # 计算差分  
2 3 6 7 8  
1 1 3 1 1  

> diff(zr)  
2 3 7 8  
1 1 1 1 

zoo对象的类型转换

首先,把对象从其他类型转型到zoo类型。

> as.zoo(rnorm(5))  # 把一个基本类型的向量转型到zoo类型  
         1          2          3          4          5  
-0.4892119  0.5740950  0.7128003  0.6282868  1.0289573  
> as.zoo(ts(rnorm(5), start = 1981, freq = 12))  
   1981(1)    1981(2)    1981(3)    1981(4)    1981(5)  
 2.3198504  0.5934895 -1.9375893 -1.9888237  1.0944444  

> x <- as.zoo(ts(rnorm(5), start = 1981, freq = 12)); x  # 把一个ts类型转型到zoo类型  
1981(1)    1981(2)    1981(3)    1981(4)    1981(5)  
1.8822996  1.6436364  0.1260436 -2.0360960 -0.1387474 

其次,把对象从zoo类型转型到其他类型。

> as.matrix(x)  # 把zoo类型,转型到矩阵  
                 x  
1981(1)  1.8822996  
1981(2)  1.6436364  
1981(3)  0.1260436  
1981(4) -2.0360960  
1981(5) -0.1387474  

> as.vector(x)  # 把zoo类型,转型到数字向量  
[1]  1.8822996  1.6436364  0.1260436 -2.0360960 -0.1387474  

> as.data.frame(x)  # 把zoo类型,转型到数据框  
                 x  
1981(1)  1.8822996  
1981(2)  1.6436364  
1981(3)  0.1260436  
1981(4) -2.0360960  
1981(5) -0.1387474  

> as.list(x)  # 把zoo类型,转型到列表  
[[1]]  
   1981(1)    1981(2)    1981(3)    1981(4)    1981(5)  
 1.8822996  1.6436364  0.1260436 -2.0360960 -0.1387474 

用ggplot2画时间序列

由于ggplot2不支持zoo类型的数据,因此需要通过ggplot2::fortify()函数,调用zoo::fortify.zoo()函数,把zoo类型转换成ggplot2可识别的类型后,ggplot2才可以对zoo类型数据的画图。以下代码用ggplot2画zoo类型的时间序列图.

library(ggplot2)  # 加载ggplot2包  
library(scales)  
x.Date <- as.Date(paste(2003, 02, c(1, 3, 7, 9, 14), sep = "-"))  # 构建数据对象  
x <- zoo(rnorm(5), x.Date)  
xlow <- x - runif(5)  
xhigh <- x + runif(5)  
z <- cbind(x, xlow, xhigh)  

                     x        xlow       xhigh  
2003-02-01 -0.36006612 -0.88751958 0.006247816  
2003-02-03  1.35216617  0.97892538 2.076360524  
2003-02-07  0.61920828  0.23746410 1.156569424  
2003-02-09  0.27516116  0.09978789 0.777878867  
2003-02-14  0.02510778 -0.80107410 0.541592929  
# 对zoo类型的数据,用fortify()转换成data.frame类型  
> g<-ggplot(aes(x = Index, y = Value), data = fortify(x, melt = TRUE))  
> g<-g+geom_line()  
> g<-g+geom_line(aes(x = Index, y = xlow), colour = "red", data = fortify(xlow))  
> g<-g+geom_ribbon(aes(x = Index, y = x, ymin = xlow, ymax = xhigh), data =  
  fortify(x), fill = "darkgray")  
> g<-g+geom_line()  
> g<-g+xlab("Index") + ylab("x")  
> g 

这里写图片描述

zoo对象的数据操作

使用coredata()函数修改zoo类型的数据部分

x.date <- as.Date(paste(2003, rep(1:4, 4:1), seq(1,20,2), sep = "-"))  
x <- zoo(matrix(rnorm(20), ncol = 2), x.date)  
coredata(x) <- matrix(1:20, ncol = 2)  # 修改数据部分  

使用index()函数修改zoo类型的索引部分

x.date <- as.Date(paste(2003, rep(1:4, 4:1), seq(1,20,2), sep = "-"))  
x <- zoo(matrix(rnorm(20), ncol = 2), x.date)  
index(x) <- 1:nrow(x)  # 修改索引部分

使用window.zoo()函数按时间过滤数据

> x.date <- as.Date(paste(2003, rep(1:4, 4:1), seq(1,20,2), sep = "-"))  
> x <- zoo(matrix(rnorm(20), ncol = 2), x.date)  

> window(x, start = as.Date("2003-02-01"), end = as.Date("2003-03-01"))  
# 取日期从2003-02-01到2003-03-01之间的数据  
2003-02-09  0.7021167 -0.3073809  
2003-02-11  2.5071111  0.6210542  
2003-02-13 -1.8900271  0.1819022  

> window(x, index = x.date[1:6], start = as.Date("2003-02-01"))  
# 取日期从2003-02-01开始的,且索引日期在x.date[1:6]中的数据  
2003-02-09 0.7021167 -0.3073809  
2003-02-11 2.5071111  0.6210542  
> window(x, index = x.date[c(4, 8, 10)])  # 取索引日期在x.date[c(4, 8, 10)]中的数据  
2003-01-07  1.4623515 -1.198597  
2003-03-15 -0.5898128  1.318401  
2003-04-19 -0.4209979 -1.648222

使用merge.zoo()合并多个zoo对象

> y1 <- zoo(matrix(1:10, ncol = 2), 1:5);y1  # 创建2个zoo数据  
1 1  6  
2 2  7  
3 3  8  
4 4  9  
5 5 10  

> y2 <- zoo(matrix(rnorm(10), ncol = 2), 3:7);y2  
3  1.4810127  0.13575871  
4 -0.3914258  0.06404148  
5  0.6018237  1.85017952  
6  1.2964150 -0.12927481  
7  0.2211769  0.32381709  

> merge(y1, y2, all = FALSE)  # 以相同的索引值合并数据  
  y1.1 y1.2       y2.1       y2.2  
3    3    8  0.9514985  1.7238941  
4    4    9 -1.1131230 -0.2061446  
5    5   10  0.6169665 -1.3141951  

> merge(y1, y2, all = FALSE, suffixes = c("a", "b"))  # 自定义数据列的名字  
  a.1 a.2        b.1        b.2  
3   3   8  0.9514985  1.7238941  
4   4   9 -1.1131230 -0.2061446  
5   5  10  0.6169665 -1.3141951  

> merge(y1, y2, all = TRUE)  # 合并完整的数据集,空数据默认以NA填充  
  y1.1 y1.2       y2.1       y2.2  
1    1    6         NA         NA  
2    2    7         NA         NA  
3    3    8  0.9514985  1.7238941  
4    4    9 -1.1131230 -0.2061446  
5    5   10  0.6169665 -1.3141951  
6   NA   NA  0.5134937  0.0634741  
7   NA   NA  0.3694591 -0.2319775  

> merge(y1, y2, all = TRUE, fill = 0)  # 合并完整的数据集,空数据以0填充  
  y1.1 y1.2       y2.1       y2.2  
1    1    6  0.0000000  0.0000000  
2    2    7  0.0000000  0.0000000  
3    3    8  0.9514985  1.7238941  
4    4    9 -1.1131230 -0.2061446  
5    5   10  0.6169665 -1.3141951  
6    0    0  0.5134937  0.0634741  
7    0    0  0.3694591 -0.2319775

使用aggregate.zoo()函数对zoo数据进行计算

> x.date <- as.Date(paste(2004, rep(1:4, 4:1), seq(1,20,2), sep = "-"))  
# 创建zoo类型数据集x  
> x <- zoo(rnorm(12), x.date); x  
 2004-01-01  2004-01-03  2004-01-05  2004-01-07  2004-02-09  2004-02-11  
 0.67392868  1.95642526 -0.26904101 -1.24455152 -0.39570292  0.09739665  
 2004-02-13  2004-03-15  2004-03-17  2004-04-19  
-0.23838695 -0.41182796 -1.57721805 -0.79727610  

> x.date2 <- as.Date(paste(2004, rep(1:4, 4:1), 1, sep = "-")); x.date2  
# 创建时间向量x.date2  
 [1] "2004-01-01" "2004-01-01" "2004-01-01" "2004-01-01" "2004-02-01"  
 [6] "2004-02-01" "2004-02-01" "2004-03-01" "2004-03-01" "2004-04-01"  

> x2 <- aggregate(x, x.date2, mean); x2  # 计算x以x.date2为时间分割规则的均值  
2004-01-01 2004-02-01 2004-03-01 2004-04-01  
 0.2791904 -0.1788977 -0.9945230 -0.7972761 

zoo对象数据函数化处理

使用rollapply()函数对zoo数据进行函数化处理

从起始日开始,计算连续几日的均值

> z <- zoo(11:15, as.Date(31:35))  

> rollapply(z, 2, mean)  # 从起始日开始,计算连续2日的均值  
1970-02-01 1970-02-02 1970-02-03 1970-02-04  
      11.5       12.5       13.5       14.5  
> rollapply(z, 3, mean)  # 从起始日开始,计算连续3日的均值  
1970-02-02 1970-02-03 1970-02-04  
        12         13         14 

等价操作变换:用rollapply()实现aggregate()的操作

> z2 <- zoo(rnorm(6))  
> rollapply(z2, 3, mean, by = 3) # means of nonoverlapping groups of 3  ; 3项求均值,by每次平移3个
         2          5  
-0.3065197  0.6350963  
> aggregate(z2, c(3,3,3,6,6,6), mean) # same 333 666求均值 
         3          6  
-0.3065197  0.6350963 

等价操作变换:用rollapply()实现rollmean()的操作

> rollapply(z2, 3, mean) # uses rollmean which is optimized for mean  
         2          3          4          5  
-0.3065197 -0.7035811 -0.1672344  0.6350963  
> rollmean(z2, 3) # same  
         2          3          4          5  
-0.3065197 -0.7035811 -0.1672344  0.6350963

NA值处理

使用na.fill()函数进行NA填充

> z <- zoo(c(NA, 2, NA, 3, 4, 5, 9, NA));z  # 创建有NA值的zoo对象  
1  2  3  4  5  6  7  8  
NA  2 NA  3  4  5  9 NA  

> na.fill(z, "extend")  # 用extend的方法,填充NA值,即NA前后项的均值填充  
  1   2   3   4   5   6   7   8  
2.0 2.0 2.5 3.0 4.0 5.0 9.0 9.0  

> na.fill(z, -(1:3))    # 自定义填充NA值,即-(1:3)循环填充  
 1  2  3  4  5  6  7  8  
-1  2 -2  3  4  5  9 -3  

> na.fill(z, c("extend", NA))  # 用extend,配合自定义的方法,即extend和自定义规则循环填充  
 1  2  3  4  5  6  7  8  
 2  2 NA  3  4  5  9  9 

使用na.aggregate()函数的统计计算的值替换NA值

> z <- zoo(c(1, NA, 3:9),c(as.Date("2010-01-01") + 0:2,as.Date("2010-02-01") +  
 0:2,as.Date("2011-01-01") + 0:2));z  
2010-01-01 2010-01-02 2010-01-03 2010-02-01 2010-02-02 2010-02-03 2011-01-01  
         1         NA          3          4          5          6          7  
2011-01-02 2011-01-03  
         8          9  

> na.aggregate(z)   # 计算排除NA的其他项的均值,替换NA值  
2010-01-01 2010-01-02 2010-01-03 2010-02-01 2010-02-02 2010-02-03 2011-01-01  
     1.000      5.375      3.000      4.000      5.000      6.000      7.000  
2011-01-02 2011-01-03  
     8.000      9.000  

> na.aggregate(z, as.yearmon)    # 以索引的年月分组的均值,替换NA值  
2010-01-01 2010-01-02 2010-01-03 2010-02-01 2010-02-02 2010-02-03 2011-01-01  
         1          2          3          4          5          6          7  
2011-01-02 2011-01-03  
         8          9  

> na.aggregate(z, months)   # 以索引的月份分组的均值,替换NA值  
2010-01-01 2010-01-02 2010-01-03 2010-02-01 2010-02-02 2010-02-03 2011-01-01  
       1.0        5.6        3.0        4.0        5.0        6.0        7.0  
2011-01-02 2011-01-03  
       8.0        9.0  

> na.aggregate(z, format, "%Y")  # 以正则表示的索引的年份分组的均值,替换NA值  
2010-01-01 2010-01-02 2010-01-03 2010-02-01 2010-02-02 2010-02-03 2011-01-01  
       1.0        3.8        3.0        4.0        5.0        6.0        7.0  
2011-01-02 2011-01-03  
       8.0        9.0 

使用na.approx()函数计算插值替换NA值

> z <- zoo(c(2, NA, 1, 4, 5, 2), c(1, 3, 4, 6, 7, 8));z  
 1  3  4  6  7  8  
 2 NA  1  4  5  2  

> na.approx(z)  
       1        3        4        6        7        8  
2.000000 1.333333 1.000000 4.000000 5.000000 2.000000  

> na.approx(z, 1:6)  
  1   3   4   6   7   8  
2.0 1.5 1.0 4.0 5.0 2.0 

使用na.StructTS()函数计算季节Kalman滤波替换NA值

> z <- zooreg(rep(10 * seq(4), each = 4) + rep(c(3, 1, 2, 4), times = 4),  
            start = as.yearqtr(2000), freq = 4)  
> z[10] <- NA  
> zout <- na.StructTS(z);zout  
> plot(cbind(z, zout), screen = 1, col = 1:2, type = c("l", "p"), pch = 20) 

这里写图片描述

使用na.trim()函数,去掉有NA的行

> xx <- zoo(matrix(c(1, 4, 6, NA, NA, 7), 3), c(2, 4, 6));xx  
2 1 NA  
4 4 NA  
6 6  7  
> na.trim(xx)  
6 6 7 

数据显示格式

> x <- as.yearqtr(2000 + seq(0, 7)/4);x  # 以年季默认格式输出  
[1] "2000 Q1" "2000 Q2" "2000 Q3" "2000 Q4" "2001 Q1" "2001 Q2" "2001 Q3"  
[8] "2001 Q4"  
> format(x, "%Y Quarter %q")  # 以年季自定义格式输出  
[1] "2000 Quarter 1" "2000 Quarter 2" "2000 Quarter 3" "2000 Quarter 4"  
[5] "2001 Quarter 1" "2001 Quarter 2" "2001 Quarter 3" "2001 Quarter 4"  
> as.yearqtr("2001 Q2")  
[1] "2001 Q2"  
> as.yearqtr("2001 q2")  
[1] "2001 Q2"  
> as.yearqtr("2001-2")  # 这里的2表示第二个季度
[1] "2001 Q2"  
以“年+月份”格式输出  
> x <- as.yearmon(2000 + seq(0, 23)/12) ;x # 以年月默认格式输出  
[1] "一月 2000"   "二月 2000"   "三月 2000"   "四月 2000"   "五月 2000"  
[6] "六月 2000"   "七月 2000"   "八月 2000"   "九月 2000"   "十月 2000"  
[11] "十一月 2000" "十二月 2000" "一月 2001"   "二月 2001"   "三月 2001"  
[16] "四月 2001"   "五月 2001"   "六月 2001"   "七月 2001"   "八月 2001"  
[21] "九月 2001"   "十月 2001"   "十一月 2001" "十二月 2001"  
> as.yearmon("mar07", "%b%y")  
[1] NA  
> as.yearmon("2007-03-01")  
[1] "三月 2007"  
> as.yearmon("2007-12")  
[1] "十二月 2007" 

区间分割

使用xblock()函数,以不同的颜色划分3个区间,即(-Inf,15)、[15,30]和(30,Inf)

> set.seed(0)  
> flow <- ts(filter(rlnorm(200, mean = 1), 0.8, method = "r"))  #产生ar(1)模型 xt)=0.8x(t-1)+e(t)
> rgb <- hcl(c(0, 0, 260), cc = c(100, 0, 100), l = c(50, 90, 50), alpha = 0.3)  
> plot(flow)  
> xblocks(flow > 30, col = rgb[1]) ## high values red  
> xblocks(flow < 15, col = rgb[3]) ## low value blue  
> xblocks(flow >= 15 & flow <= 30, col = rgb[2]) ## the rest gray 

这里写图片描述

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值