第 3 章 高性能时间序列分析

3.1 创建时间序列对象的性能测试

所需 R 包。

library(zoo) 
library(xts) 
library(timeSeries) 

定义一个 systemTime 函数来度量各种操作的效率。

systemTime <-function(expr, gcFirst = TRUE, n = 20) {
time <-sapply(integer(n), eval.parent(substitute(function(...)
system.time(expr, gcFirst = gcFirst))))
structure(apply(time, 1, median), class = "proc_time")
}

基于字符型时间戳,创建一个时期跨度为 100 年,列数为 5 的日时间序列对象需要多长时间?

R 会从 ASCII 格式,网页,或者 xls 与 csv 文件中读入时间序列数据后,通常将数据存储为字符串。

为了将字符串转化为 zoo、xts 或者 timeSeries 对象,需先将时间戳转化为合适的标签。考虑一个时期跨度为 100 年、共 35000 条记录的日时间序列数据。

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"),
to = as.Date("1999-12-31"), by = "day"))
data <-matrix(rnorm(length(charvec)*5), ncol = 5)

zoo:

systemTime(zoo(data, charvec)) 
##    user  system elapsed 
##  0.0515  0.0000  0.0530

xts:

print(try(xts(data, charvec))) 

timeSeries:

systemTime(timeSeries(data, charvec)) 
##    user  system elapsed 
##   0.196   0.003   0.202

3.1.1 基于日期型时间戳,创建一个时期跨度为 100 年、列数为 5 的日时间序列对

象需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), 
to = as.Date("1999-12-31"), by = "day"))
data <-matrix(rnorm(length(charvec)*5), ncol = 5)
index <-as.Date(charvec)
class(index)
## [1] "Date"

zoo:

systemTime(zoo(data, index)) 
##    user  system elapsed 
##   0.006   0.000   0.006

这是基于 zoo 包创建时间序列对象的基本方法。

xts:

systemTime(xts(data, index)) 
##    user  system elapsed 
##   0.001   0.000   0.001

这是基于 xts 包创建时间序列对象的基本做法。

timeSeries:

systemTime(timeSeries(data, index)) 
##    user  system elapsed 
##   0.003   0.000   0.003

鉴于金融时间序列分析的对象大都是 timeDate 对象,下面的操作效率可以作为一个效率基准。

3.1.2 基于 GMT POSIXct 时间戳,创建一个时期跨度为 100 年、列数为 5 的日时间序列对象需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), 
to = as.Date("1999-12-31"), by = "day"))
data <-matrix(rnorm(length(charvec)*5), ncol = 5)
index <-as.POSIXct(charvec, tz = "GMT")
class(index)
## [1] "POSIXct" "POSIXt"

zoo:

systemTime(zoo(data, index)) 
##    user  system elapsed 
##   0.006   0.000   0.006

xts:

systemTime(xts(data, index)) 
##    user  system elapsed 
##   0.000   0.000   0.001

timeSeries:

systemTime(timeSeries(data, index)) 
##    user  system elapsed 
##   0.003   0.000   0.003

3.1.3 基于非 GMT POSIXct 时间戳,创建一个时期跨度为 100 年、列数为 5 的日时间序列对象需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), 
to = as.Date("1999-12-31"), by = "day"))
data <-matrix(rnorm(length(charvec)*5), ncol = 5)
#index <-as.POSIXct(charvec, tz = "CET")
#class(index)

zoo:

systemTime(zoo(data, index)) 
##    user  system elapsed 
##   0.006   0.000   0.006

xts:

systemTime(xts(data, index)) 
##    user  system elapsed 
##   1e-03   0e+00   5e-04

timeSeries:

systemTime(timeSeries(data, index)) 
##    user  system elapsed 
##   0.003   0.000   0.003

3.1.4 基于 timeDate 型时间戳,创建一个时期跨度为 100 年、列数为 5 的日时间序列对象需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), to = as.Date("1999-12-31"), by = "day"))
data <-matrix(rnorm(length(charvec)*5), ncol = 5)
index <-timeDate(charvec)
class(index)
## [1] "timeDate"
## attr(,"package")
## [1] "timeDate"

zoo:

systemTime(zoo(data, index)) 
##    user  system elapsed 
##  0.0060  0.0000  0.0065

xts:

systemTime(xts(data, index)) 
##    user  system elapsed 
##   0.001   0.000   0.001

timeSeries:

systemTime(timeSeries(data, index)) 
##    user  system elapsed 
##   0.001   0.000   0.001

3.2 对时间序列取子集的操作性能

所需 R 包。

library(zoo) 
library(xts) 
library(timeSeries) 

定义一个 systemTime 函数来度量各种操作性能。

systemTime <-function(expr, gcFirst = TRUE, n = 20) {
time <-sapply(integer(n), eval.parent(substitute(function(...)
system.time(expr, gcFirst = gcFirst))))
structure(apply(time, 1, median), class = "proc_time")
}

3.2.1 基于整数,对时期跨度为 100 年,列数为 5的日时间序列对象进行取子集操作需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), 
to = as.Date("1999-12-31"), by = "day"))
data <-matrix(rnorm(length(charvec)*5), ncol = 5)
index <-charvec
length <-floor(length(charvec)/2)
subset <-sample(charvec)[1:length]

zoo:

z <-zoo(data, as.Date(charvec))
systemTime(z[subset, ])
##    user  system elapsed 
##   0.089   0.002   0.093

xts:

x <-xts(data, as.Date(charvec)) 

该操作耗时巨大!

timeSeries:

s <-timeSeries(data, charvec)
systemTime(s[subset, ])
##    user  system elapsed 
##   0.113   0.002   0.117

3.2.2 基于 Date 对象,对时期跨度为 100 年,列数为 5 的日时间序列对象进行取子集操作需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), 
to = as.Date("1999-12-31"), by = "day"))
data <-matrix(rnorm(length(charvec)*5), ncol = 5)
index <-as.Date(charvec)
length <-floor(length(charvec)/2)
subset <-as.Date(sample(charvec)[1:length])

zoo:

z <-zoo(data, index)
systemTime(z[subset, ])
##    user  system elapsed 
##  0.0060  0.0010  0.0065

xts:

x <-xts(data, index) 

该操作耗时巨大。

timeSeries:

s <-timeSeries(data, index)
systemTime(s[subset, ])
##    user  system elapsed 
##   0.006   0.000   0.006

3.2.3 基于 Date 对象,对一个时期跨度为 100 年,列数为 5 的 GMT POSIXct 格式的日时间序列进行取子集操作需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), 
to = as.Date("1999-12-31"), by = "day")) 
data <-matrix(rnorm(length(charvec)*5), ncol = 5) 
index <-as.POSIXct(charvec, tz = "GMT") 
length <-floor(length(charvec)/2) 
subset <-as.POSIXct(sample(charvec)[1:length], tz = "GMT") 

zoo:

z <-zoo(data, index)
systemTime(z[subset, ])
##    user  system elapsed 
##   0.005   0.001   0.007

xts:

x <-xts(data, index) 

该操作耗时巨大!

timeSeries:

s <-timeSeries(data, index) 
systemTime(s[subset, ]) 
##    user  system elapsed 
##   0.006   0.000   0.006

3.2.4 基于 Date 对象,对一个时期跨度为 100 年,列数为 5 的非 GMT POSIXct 格式的日时间序列进行取子集操作需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), 
to = as.Date("1999-12-31"), by = "day")) 
data <-matrix(rnorm(length(charvec)*5), ncol = 5) 
index <-as.POSIXct(charvec, format="%Y-%m-%d",tz = "CET") 

length <-floor(length(charvec)/2) 
subset <-as.POSIXct(sample(charvec)[1:length], tz = "GMT") 

zoo:

z <-zoo(data, index)
## Warning in zoo(data, index): some methods for
## "zoo" objects do not work if the index entries in
## 'order.by' are not unique
systemTime(z[subset, ])
##    user  system elapsed 
##   0.003   0.000   0.003

xts:

x <-xts(data, order.by=index) 

该操作耗时巨大!

timeSeries:

s <-timeSeries(data, index) 

这里有问题。

3.2.5 基于 Date 对象,对一个时期跨度为 100 年,列数为 5 的以 GMT timeDate 对象形式存储的日时间序列进行取子集操作需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), to = as.Date("1999-12-31"), by = "day"))
data <-matrix(rnorm(length(charvec)*5), ncol = 5)
index <-timeDate(charvec)
length <-floor(length(charvec)/2)
subset <-timeDate(sample(charvec)[1:length])

zoo:

z <-zoo(data, index)
systemTime(z[subset, ])
##    user  system elapsed 
##   0.006   0.001   0.007

zoo 会自动经 fCalendar 包调用旧版本的 timeDate 函数,因此要 detach。

xts:

该操作耗时巨大!

timeSeries:

s <-timeSeries(data, index)
systemTime(s[subset, ])
##    user  system elapsed 
##   0.004   0.000   0.004

3.2.6 基于 Date 对象,对一个时期跨度为 100 年,列数为 5 的以 GMT timeDate 对象形式存储的日时间序列进行取子集操作需要多长时间?

常规数据

charvec <-format(seq(from = as.Date("1901-01-01"), to = as.Date("1999-12-31"), by = "day")) 
data <-matrix(rnorm(length(charvec)*5), ncol = 5) 
index <-timeDate(charvec, zone = "Zurich", FinCenter = "Zurich") 
length <-floor(length(charvec)/2) 
subset <-timeDate(sample(charvec)[1:length], zone = "Zurich",FinCenter = "Zurich")

zoo:

z <-zoo(data,index)
systemTime(z[subset,])
##    user  system elapsed 
##   0.006   0.001   0.007

xts:

x <- xts(data,index)
#systemTime(x[subset, ])

timeSeries:

s <- timeSeries(data, index)
systemTime(s[subset, ])
##    user  system elapsed 
##   0.005   0.000   0.005