knitr::opts_knit$set(root.dir = 'C:/Users/neide/Documents/GitHub/sigex')

Airline

We examine the "International Airline Passengers" data from Box and Jenkins' book, referred to as airline for short. The data covers a span from January 1949 through December 1960, and exhibits trend and seasonality.

Loading Packages

This code loads the code, and the data into a variable named airline.

## wipe
rm(list=ls())
library(devtools)
library(Rcpp)

load_all(".")
root.dir <- getwd()

airline <-  c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118,
    115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140,
    145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166,
    171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194,
    196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201,
    204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229,
    242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278,
    284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306,
    315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336,
    340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337,
    360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405,
    417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432)

Enter Metadata

start.time = c(1949,1)
period <- 12
dataALL.ts <- sigex.load(as.matrix(airline),start.time,period,
                         c("Airline"),TRUE)

Select Spans and Transforms

transform <- "log"
aggregate <- FALSE
subseries <- 1
range <- NULL
end.time <- end(dataALL.ts)
data.ts <- sigex.prep(dataALL.ts,transform,aggregate,subseries,range,TRUE)

Spectral Exploratory Analysis

# raw data
par(mfrow=c(1,1))
for(i in 1:length(subseries))
{
  sigex.specar(data.ts,FALSE,i,period)
}
dev.off()
# growth rates
par(mfrow=c(1,1))
for(i in 1:length(subseries))
{
  sigex.specar(data.ts,TRUE,i,period)
}
dev.off()

Model Declaration

N <- dim(data.ts)[2]
T <- dim(data.ts)[1]
start.date <- c(start.time[2],1,start.time[1])
if(end.time[2] == 12) { end.day <- 31 } else
{ end.day <- date2day(end.time[2]+1,1,end.time[1]) - date2day(end.time[2],1,end.time[1]) }
end.date <- c(end.time[2],end.day,end.time[1])
td.weights <- NULL
for(i in 1:7) 
{
  td.weights <- cbind(td.weights,daily2monthly(rep(1,T*35),start.date,i)[,1])
}
td.weights <- td.weights[1:T,2:7] - td.weights[1:T,1]
easter.dates <- read.table(paste(root.dir,"/data/easter500.txt",sep=""))
easter.reg <- gethol(easter.dates,1,0,start.date,end.date)
easter.regs <- NULL
for(i in 1:7) 
{ 
  easter.regs <- cbind(easter.regs,daily2monthly(easter.reg,start.date,i)[,1]) 
}
easter.regs <- rowSums(easter.regs)

Model Construction and Fitting

delta.seas <- c(1,-1,rep(0,period-2),-1,1)
mdl <- NULL
mdl <- sigex.add(mdl,seq(1,N),"sarma",c(0,1,0,1,12),NULL,"process",delta.seas)
mdl <- sigex.meaninit(mdl,data.ts,0)
mdl <- sigex.reg(mdl,1,ts(td.weights[,1,drop=FALSE],start=start.time,
                          frequency=period,names="TD Monday"))
mdl <- sigex.reg(mdl,1,ts(td.weights[,2,drop=FALSE],start=start.time,
                          frequency=period,names="TD Tuesday"))
mdl <- sigex.reg(mdl,1,ts(td.weights[,3,drop=FALSE],start=start.time,
                          frequency=period,names="TD Wednesday"))
mdl <- sigex.reg(mdl,1,ts(td.weights[,4,drop=FALSE],start=start.time,
                          frequency=period,names="TD Thursday"))
mdl <- sigex.reg(mdl,1,ts(td.weights[,5,drop=FALSE],start=start.time,
                          frequency=period,names="TD Friday"))
mdl <- sigex.reg(mdl,1,ts(td.weights[,6,drop=FALSE],start=start.time,
                          frequency=period,names="TD Saturday"))
mdl <- sigex.reg(mdl,1,ts(as.matrix(easter.regs),start=start.time,
                          frequency=period,names="Easter"))
constraint <- NULL
constraint <- rbind(constraint,sigex.constrainreg(mdl,data.ts,list(seq(2,6)),NULL))
par.mle <- sigex.default(mdl,data.ts,constraint)
psi.mle <- sigex.par2psi(par.mle,mdl)
fit.mle <- sigex.mlefit(data.ts,par.mle,constraint,mdl,"bfgs",debug=FALSE)
psi.mle <- sigex.eta2psi(fit.mle[[1]]$par,constraint)
hess <- fit.mle[[1]]$hessian
par.mle <- fit.mle[[2]]
print(eigen(hess)$values)
resid.mle <- sigex.resid(psi.mle,mdl,data.ts)[[1]]
resid.mle <- sigex.load(t(resid.mle),start(data.ts),frequency(data.ts),colnames(data.ts),TRUE)
resid.acf <- acf(resid.mle,lag.max=4*period,plot=TRUE)$acf
analysis.mle <- sigex.bundle(data.ts,transform,mdl,psi.mle)

SEATS Signal Extraction

Canonical Decomposition

airlineDecomp <- function(theta)
{
    #       function to compute canonical decomposition for given airline model
    #       input: theta has nonseasonal theta and seasonal theta, in Box-Jenkins notation
    #       output: trendirreg is two moving average parameters,
  #             and innovation variance for nonseasonal
    #                   seasonal is eleven moving average parameters,
  #             and innovation variance for seasonal
  # Requires: polymult.r, specFact.r

    temp <- polymult(c(1,-1*theta[1]),c(1,rep(0,11),-1*theta[2]))           
    gamma <- polymult(temp,rev(temp))[14:27]

    # Compute partial fraction decomposition
    Amat <- matrix(0,nrow=14,ncol=14)
    Amat[,1] <- c(12,11,10,9,8,7,6,5,4,3,2,1,0,0)
    Amat[,2] <- c(22,22,20,18,16,14,12,10,8,6,4,2,1,0)
    Amat[,3] <- c(6,-4,1,rep(0,11))
    Amat[,4] <- c(-8,7,-4,1,rep(0,10))
    Amat[,5] <- c(2,-4,6,-4,1,rep(0,9))
    Amat[,6] <- c(0,1,-4,6,-4,1,rep(0,8))
    Amat[,7] <- c(0,0,1,-4,6,-4,1,rep(0,7))
    Amat[,8] <- c(rep(0,3),1,-4,6,-4,1,rep(0,6))
    Amat[,9] <- c(rep(0,4),1,-4,6,-4,1,rep(0,5))
    Amat[,10] <- c(rep(0,5),1,-4,6,-4,1,rep(0,4))
    Amat[,11] <- c(rep(0,6),1,-4,6,-4,1,rep(0,3))
    Amat[,12] <- c(rep(0,7),1,-4,6,-4,1,rep(0,2))
    Amat[,13] <- c(rep(0,8),1,-4,6,-4,1,0)
    Amat[,14] <- c(4,-2,rep(0,9),1,-2,1)
    Ainv <- solve(Amat)
    pfrac <- Ainv %*% gamma

    # Define spectra functions for seasonal and nonseasonal, to be minimized.
    # Lambda is a frequency between 0 and 1.
    seasFunc <- function(lambda,varP)
    {
        cosvec <- cbind(cos(pi*lambda),cos(pi*2*lambda),cos(pi*3*lambda),
                        cos(pi*4*lambda),cos(pi*5*lambda),cos(pi*6*lambda),
                        cos(pi*7*lambda),cos(pi*8*lambda),cos(pi*9*lambda),cos(pi*10*lambda))
        numer <- varP[3] + 2*varP[4:13]%*%t(cosvec)
        denom <- abs(12 + 2*(12-seq(1:11))%*%t(cbind(cosvec,cos(pi*11*lambda))))
        return(numer/denom)
    }
    trendFunc <- function(lambda,varP)
    {
        numer <- varP[1] + 2*varP[2]*cos(pi*lambda)
        denom <- 6 - 8*cos(pi*lambda) + 2*cos(pi*2*lambda)
        return(numer/denom)
    }

    # Compute minima of these functions
    lambVec <- seq(1,10000)/10000
    tol <- 0
    Smin <- min(seasFunc(lambVec,pfrac))
    Smin <- Smin - tol
    Tmin <- min(trendFunc(lambVec,pfrac))

    # Compute new spectra
    irrVar <- pfrac[14] + Smin + Tmin
    seasACF <- c(pfrac[3:13],0) -1*Smin*(13-seq(1:12))
    trendACF <- c(pfrac[1:2],0) -1*Tmin*c(6,-4,1)
    saACF <- trendACF + c(6,-4,1)*irrVar

    # Compute spectral decompositions
    seasMA <- specFact(c(rev(seasACF),seasACF[-1]))
    trendMA <- specFact(c(rev(trendACF),trendACF[-1]))
    saMA <- specFact(c(rev(saACF),saACF[-1]))
    seasMA <- c(seasMA[-1]/seasMA[1],seasMA[1]^2)
    trendMA <- c(trendMA[-1]/trendMA[1],trendMA[1]^2)
    saMA <- c(saMA[-1]/saMA[1],saMA[1]^2)

    return(list(Re(trendMA),Re(seasMA),Re(irrVar),Re(saMA)))
}   

air.out <- airlineDecomp(par.mle[[3]][[1]])
mdl2 <- NULL
mdl2 <- sigex.add(mdl2,seq(1,N),"arma",c(0,2),NULL,"trend",c(1,-2,1))
mdl2 <- sigex.add(mdl2,seq(1,N),"arma",c(0,11),NULL,"seasonal",rep(1,12))
mdl2 <- sigex.add(mdl2,seq(1,N),"arma",c(0,0),NULL,"irregular",1)
mdl2 <- sigex.meaninit(mdl2,data.ts,0)
mdl2 <- sigex.reg(mdl2,1,ts(td.weights[,1,drop=FALSE],start=start.time,
                          frequency=period,names="TD Monday"))
mdl2 <- sigex.reg(mdl2,1,ts(td.weights[,2,drop=FALSE],start=start.time,
                          frequency=period,names="TD Tuesday"))
mdl2 <- sigex.reg(mdl2,1,ts(td.weights[,3,drop=FALSE],start=start.time,
                          frequency=period,names="TD Wednesday"))
mdl2 <- sigex.reg(mdl2,1,ts(td.weights[,4,drop=FALSE],start=start.time,
                          frequency=period,names="TD Thursday"))
mdl2 <- sigex.reg(mdl2,1,ts(td.weights[,5,drop=FALSE],start=start.time,
                          frequency=period,names="TD Friday"))
mdl2 <- sigex.reg(mdl2,1,ts(td.weights[,6,drop=FALSE],start=start.time,
                          frequency=period,names="TD Saturday"))
mdl2 <- sigex.reg(mdl2,1,ts(as.matrix(easter.regs),start=start.time,
                          frequency=period,names="Easter"))
constraint <- NULL
constraint <- rbind(constraint,sigex.constrainreg(mdl2,data.ts,list(seq(2,6)),NULL))
par.mle2 <- sigex.default(mdl2,data.ts,constraint)
par.mle2[[2]][[1]] <- air.out[[1]][3]*exp(par.mle[[2]][[1]])
par.mle2[[2]][[2]] <- air.out[[2]][12]*exp(par.mle[[2]][[1]])
par.mle2[[2]][[3]] <- air.out[[3]][1]*exp(par.mle[[2]][[1]])
par.mle2[[3]][[1]] <- matrix(air.out[[1]][1:2],nrow=1,ncol=2)
par.mle2[[3]][[2]] <- matrix(air.out[[2]][1:11],nrow=1,ncol=11)
par.mle2[[4]] <- par.mle[[4]]
psi.mle2 <- sigex.par2psi(par.mle2,mdl2)

Direct Matrix Approach

signal.trend <- sigex.signal(data.ts,par.mle2,mdl2,1)
signal.seas <- sigex.signal(data.ts,par.mle2,mdl2,2)
signal.sa <- sigex.signal(data.ts,par.mle2,mdl2,c(1,3))
extract.trend <- sigex.extract(data.ts,signal.trend,mdl2,par.mle2)
extract.seas <- sigex.extract(data.ts,signal.seas,mdl2,par.mle2)
extract.sa <- sigex.extract(data.ts,signal.sa,mdl2,par.mle2)
reg.trend <- sigex.fixed(data.ts,mdl2,1,par.mle2,"Trend")
reg.mon <- sigex.fixed(data.ts,mdl2,1,par.mle2,"TD Monday")
reg.tue <- sigex.fixed(data.ts,mdl2,1,par.mle2,"TD Tuesday")
reg.wed <- sigex.fixed(data.ts,mdl2,1,par.mle2,"TD Wednesday")
reg.thu <- sigex.fixed(data.ts,mdl2,1,par.mle2,"TD Thursday")
reg.fri <- sigex.fixed(data.ts,mdl2,1,par.mle2,"TD Friday")
reg.sat <- sigex.fixed(data.ts,mdl2,1,par.mle2,"TD Saturday")
reg.easter <- sigex.fixed(data.ts,mdl2,1,par.mle2,"Easter")
reg.seas <- reg.mon + reg.tue + reg.wed + reg.thu + reg.fri + reg.sat + reg.easter
trendcol <- "tomato"
seascol <- "seagreen"
sacol <- "navyblue"
fade <- 40
par(mfrow=c(2,1))
plot(data.ts[,1],xlab="Year",ylab="",ylim=c(min(data.ts[,1]),max(data.ts[,1])),lwd=1)
sigex.graph(extract.sa,reg.trend,start.time,period,1,0,sacol,fade)
plot(ts(rep(NA,T),start=start.time,frequency=12),xlab="Year",ylab="",ylim=c(-5,5),lwd=1)
sigex.graph(extract.seas,reg.seas,start.time,period,1,0,seascol,fade)
dev.off()
## spectral diagnostics: sa
sigex.specar(ts(extract.sa[[1]],frequency=period,names=colnames(data.ts)),FALSE,1,period)
dev.off()

Filter Analysis

grid <- 200
frf.sa <- sigex.getfrf(data.ts,par.mle2,mdl2,c(1,3),TRUE,grid)
dev.off()
len <- 50
target <- array(diag(N),c(N,N,1))
wk.sa <- sigex.wk(data.ts,par.mle2,mdl2,c(1,3),target,TRUE,grid,len)
dev.off()


jlivsey/sigex documentation built on March 20, 2024, 3:17 a.m.