blob: 2e96bd7fb72eeacfd171b126edf014ef541b113c [file] [log] [blame]
# File src/library/stats/R/ar.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1999-2019 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
## based on, especially multivariate case, code by Martyn Plummer
ar <-
function (x, aic = TRUE, order.max = NULL,
method = c("yule-walker","burg", "ols", "mle", "yw"),
na.action = na.fail, series = deparse(substitute(x)), ...)
{
res <- switch(match.arg(method),
yw =,
"yule-walker" = ar.yw(x, aic = aic, order.max = order.max,
na.action = na.action, series = series, ...),
"burg" = ar.burg(x, aic = aic, order.max = order.max,
na.action = na.action, series = series, ...),
"ols" = ar.ols(x, aic = aic, order.max = order.max,
na.action = na.action, series = series, ...),
"mle" = ar.mle(x, aic = aic, order.max = order.max,
na.action = na.action, series = series, ...)
)
res$call <- match.call()
res
}
ar.yw <- function(x, ...) UseMethod("ar.yw")
ar.yw.default <-
function (x, aic = TRUE, order.max = NULL, na.action = na.fail,
demean = TRUE, series = NULL, ...)
{
if(is.null(series)) series <- deparse(substitute(x))
ists <- is.ts(x)
x <- na.action(as.ts(x))
if(ists) xtsp <- tsp(x)
xfreq <- frequency(x)
x <- as.matrix(x)
if(!is.numeric(x))
stop("'x' must be numeric")
if(any(is.na(x) != is.na(x[,1]))) stop("NAs in 'x' must be the same row-wise")
nser <- ncol(x)
if (demean) {
xm <- colMeans(x, na.rm=TRUE)
x <- sweep(x, 2L, xm, check.margin=FALSE)
} else xm <- rep.int(0, nser)
n.used <- nrow(x)
n.obs <- sum(!is.na(x[,1])) # number of non-missing rows
order.max <- if (is.null(order.max))
min(n.obs - 1L, floor(10 * log10(n.obs))) else floor(order.max)
if (order.max < 1L) stop("'order.max' must be >= 1")
else if (order.max >= n.obs) stop("'order.max' must be < 'n.obs'")
xacf <- acf(x, type = "covariance", lag.max = order.max, plot = FALSE,
demean=demean, na.action = na.pass)$acf
if(nser > 1L) {
## multivariate case
snames <- colnames(x)
A <- B <- array(0, dim = c(order.max + 1L, nser, nser))
A[1L, , ] <- B[1L, , ] <- diag(nser)
EA <- EB <- xacf[1L, , , drop = TRUE]
partialacf <- array(dim = c(order.max, nser, nser))
xaic <- numeric(order.max + 1L)
solve.yw <- function(m) {
# Solve Yule-Walker equations with Whittle's
# generalization of the Levinson(-Durbin) algorithm
betaA <- betaB <- 0
for (i in 0L:m) {
betaA <- betaA + A[i + 1L, , ] %*% xacf[m + 2L - i, , ]
betaB <- betaB + B[i + 1L, , ] %*% t(xacf[m + 2L - i, , ])
}
KA <- -t(qr.solve(t(EB), t(betaA)))
KB <- -t(qr.solve(t(EA), t(betaB)))
EB <<- (diag(nser) - KB %*% KA) %*% EB
EA <<- (diag(nser) - KA %*% KB) %*% EA
Aold <- A
Bold <- B
for (i in seq_len(m + 1L)) {
A[i + 1L, , ] <<- Aold[i + 1L, , ] + KA %*% Bold[m + 2L - i, , ]
B[i + 1L, , ] <<- Bold[i + 1L, , ] + KB %*% Aold[m + 2L - i, , ]
}
}
cal.aic <- function(m) { # (EA) omits mean params, that is constant adj
logdet <- determinant.matrix(EA)$modulus
# == log(abs(prod(diag(qr(EA)$qr))))
n.obs * logdet + 2 * m * nser * nser
}
cal.resid <- function() {
resid <- array(0, dim = c(n.used - order, nser))
for (i in 0L:order)
resid <- resid +
tcrossprod(x[(order - i + 1L):(n.used - i), , drop = FALSE],
ar[i + 1L, , ])
rbind(matrix(NA, order, nser), resid)
}
order <- 0L
for (m in 0L:order.max) {
xaic[m + 1L] <- cal.aic(m) # (EA)
if (!aic || xaic[m + 1L] == min(xaic[seq_len(m + 1L)])) {
ar <- A
order <- m
var.pred <- EA * n.obs/(n.obs - nser * (m + 1L))
}
if (m < order.max) {
solve.yw(m) #-> update (EA, EB, A, B)
partialacf[m + 1L, , ] <- -A[m + 2L, , ]
}
}
xaic <- setNames(xaic - min(xaic), 0L:order.max)
resid <- cal.resid()
if(order) {
ar <- -ar[2L:(order + 1L), , , drop = FALSE]
dimnames(ar) <- list(seq_len(order), snames, snames)
} else ar <- array(0, dim = c(0L, nser, nser),
dimnames = list(NULL, snames, snames))
dimnames(var.pred) <- list(snames, snames)
dimnames(partialacf) <- list(seq_len(order.max), snames, snames)
colnames(resid) <- colnames(x)
} else { ## univariate case
if (xacf[1L] == 0) stop("zero-variance series")
r <- as.double(drop(xacf))
z <- .Fortran(C_eureka, as.integer(order.max), r, r,
coefs = double(order.max^2),
vars = double(order.max),
double(order.max))
coefs <- matrix(z$coefs, order.max, order.max)
partialacf <- array(diag(coefs), dim = c(order.max, 1L, 1L))
var.pred <- c(r[1L], z$vars)
xaic <- n.obs * log(var.pred) + 2 * (0L:order.max) + 2 * demean
maic <- min(aic)
xaic <- setNames(if(is.finite(maic)) xaic - min(xaic) else
ifelse(xaic == maic, 0, Inf),
0L:order.max)
order <- if (aic) (0L:order.max)[xaic == 0L] else order.max
ar <- if (order) coefs[order, seq_len(order)] else numeric()
var.pred <- var.pred[order + 1L]
## Splus compatibility fix
var.pred <- var.pred * n.obs/(n.obs - (order + 1L))
resid <- if(order) c(rep.int(NA, order), embed(x, order + 1L) %*% c(1, -ar))
else as.vector(x) # we had as.matrix() above
if(ists) {
attr(resid, "tsp") <- xtsp
attr(resid, "class") <- "ts"
}
}
res <- list(order = order, ar = ar, var.pred = var.pred, x.mean = drop(xm),
aic = xaic, n.used = n.used, n.obs = n.obs, order.max = order.max,
partialacf = partialacf, resid = resid, method = "Yule-Walker",
series = series, frequency = xfreq, call = match.call())
if(nser == 1L && order)
res$asy.var.coef <- var.pred/n.obs *
solve(toeplitz(drop(xacf)[seq_len(order)]))
class(res) <- "ar"
res
}
print.ar <- function(x, digits = max(3L, getOption("digits") - 3L), ...)
{
cat("\nCall:\n", deparse(x$call), "\n\n", sep = "")
nser <- NCOL(x$var.pred)
if(nser > 1L) {
res <- x[c("ar", if(!is.null(x$x.intercept)) "x.intercept", "var.pred")]
res$ar <- aperm(res$ar, c(2L,3L,1L))
print(res, digits = digits)
} else { ## univariate case
if(x$order) {
cat("Coefficients:\n")
coef <- setNames(round(drop(x$ar), digits = digits),
seq_len(x$order))
print.default(coef, print.gap = 2L)
}
if(!is.null(xint <- x$x.intercept) && !is.na(xint))
cat("\nIntercept: ", format(xint, digits = digits),
## FIXME? asy.se.coef *only* exists for ar.ols (??)
" (", format(x$asy.se.coef$x.mean, digits = digits),
") ", "\n", sep = "")
cat("\nOrder selected", x$order, " sigma^2 estimated as ",
format(x$var.pred, digits = digits))
cat("\n")
}
invisible(x)
}
predict.ar <- function(object, newdata, n.ahead = 1L, se.fit = TRUE, ...)
{
if (n.ahead < 1L) stop("'n.ahead' must be at least 1")
if(missing(newdata)) {
newdata <- eval.parent(parse(text=object$series))
if (!is.null(nas <- object$call$na.action))
newdata <- eval.parent(call(nas, newdata))
}
nser <- NCOL(newdata)
ar <- object$ar
p <- object$order
st <- tsp(as.ts(newdata))[2L]
dt <- deltat(newdata)
xfreq <- frequency(newdata)
tsp(newdata) <- NULL
class(newdata) <- NULL
if(NCOL(ar) != nser)
stop("number of series in 'object' and 'newdata' do not match")
n <- NROW(newdata)
if(nser > 1L) {
if(is.null(object$x.intercept)) xint <- rep.int(0, nser)
else xint <- object$x.intercept
x <- rbind(sweep(newdata, 2L, object$x.mean, check.margin = FALSE),
matrix(rep.int(0, nser), n.ahead, nser, byrow = TRUE))
pred <- if(p) {
for(i in seq_len(n.ahead)) {
x[n+i,] <- ar[1L,,] %*% x[n+i-1L,] + xint
if(p > 1L) for(j in 2L:p)
x[n+i,] <- x[n+i,] + ar[j,,] %*% x[n+i-j,]
}
x[n + seq_len(n.ahead), ]
} else matrix(xint, n.ahead, nser, byrow = TRUE)
pred <- pred + matrix(object$x.mean, n.ahead, nser, byrow = TRUE)
colnames(pred) <- colnames(object$var.pred)
if(se.fit) {
warning("'se.fit' not yet implemented for multivariate models")
se <- matrix(NA, n.ahead, nser)
}
} else {
if(is.null(object$x.intercept)) xint <- 0
else xint <- object$x.intercept
x <- c(newdata - object$x.mean, rep.int(0, n.ahead))
if(p) {
for(i in seq_len(n.ahead))
x[n+i] <- sum(ar * x[n+i - seq_len(p)]) + xint
pred <- x[n + seq_len(n.ahead)]
if(se.fit) {
psi <- .Call(C_ar2ma, ar, n.ahead - 1L)
vars <- cumsum(c(1, psi^2))
se <- sqrt(object$var.pred*vars)[seq_len(n.ahead)]
}
} else {
pred <- rep.int(xint, n.ahead)
if (se.fit) se <- rep.int(sqrt(object$var.pred), n.ahead)
}
pred <- pred + rep.int(object$x.mean, n.ahead)
}
pred <- ts(pred, start = st + dt, frequency = xfreq)
if(se.fit)
list(pred = pred, se = ts(se, start = st + dt, frequency = xfreq))
else pred
}
ar.mle <- function (x, aic = TRUE, order.max = NULL, na.action = na.fail,
demean = TRUE, series = NULL, ...)
{
if(is.null(series)) series <- deparse(substitute(x))
ists <- is.ts(x)
if (!is.null(dim(x)))
stop("MLE only implemented for univariate series")
x <- na.action(as.ts(x))
if(anyNA(x)) stop("NAs in 'x'")
if(!is.numeric(x))
stop("'x' must be numeric")
if(ists) xtsp <- tsp(x)
xfreq <- frequency(x)
x <- as.vector(x) # drop attributes, including class
n.used <- length(x)
order.max <- if (is.null(order.max))
min(n.used-1L, 12L, floor(10 * log10(n.used)))
else round(order.max)
if (order.max < 0L) stop ("'order.max' must be >= 0")
else if (order.max >= n.used) stop("'order.max' must be < 'n.used'")
if (aic) {
coefs <- matrix(NA, order.max+1L, order.max+1L)
var.pred <- numeric(order.max+1L)
xaic <- numeric(order.max+1L)
xm <- if(demean) mean(x) else 0
coefs[1, 1L] <- xm
var0 <- sum((x-xm)^2)/n.used
var.pred[1L] <- var0
xaic[1L] <- n.used * log(var0) + 2 * demean + 2 + n.used + n.used * log(2 * pi)
for(i in seq_len(order.max)) {
fit <- arima0(x, order=c(i, 0L, 0L), include.mean=demean)
coefs[i+1L, seq_len(i+demean)] <- fit$coef[seq_len(i+demean)]
xaic[i+1L] <- fit$aic
var.pred[i+1L] <- fit$sigma2
}
xaic <- setNames(xaic - min(xaic), 0L:order.max)
order <- (0L:order.max)[xaic == 0L]
ar <- coefs[order+1L, seq_len(order)]
x.mean <- coefs[order+1L, order+1L]
var.pred <- var.pred[order+1L]
} else {
order <- order.max
fit <- arima0(x, order=c(order, 0L, 0L), include.mean=demean)
coefs <- fit$coef
if(demean) {
ar <- coefs[-length(coefs)]
x.mean <- coefs[length(coefs)]
} else {
ar <- coefs
x.mean <- 0
}
var.pred <- fit$sigma2
xaic <- structure(0, names=order)
}
resid <- if(order) c(rep(NA, order), embed(x - x.mean, order+1L) %*% c(1, -ar))
else x - x.mean
if(ists) {
attr(resid, "tsp") <- xtsp
attr(resid, "class") <- "ts"
}
res <- list(order = order, ar = ar, var.pred = var.pred,
x.mean = x.mean, aic = xaic,
n.used = n.used, n.obs = n.used, order.max = order.max,
partialacf = NULL, resid = resid, method = "MLE",
series = series, frequency = xfreq, call = match.call())
if(order) {
xacf <- acf(x, type = "covariance", lag.max = order, plot=FALSE)$acf
res$asy.var.coef <- var.pred/n.used *
solve(toeplitz(drop(xacf)[seq_len(order)]))
}
class(res) <- "ar"
res
}
## original code by Adrian Trapletti
ar.ols <- function (x, aic = TRUE, order.max = NULL, na.action = na.fail,
demean = TRUE, intercept = demean, series = NULL, ...)
{
if(is.null(series)) series <- deparse(substitute(x))
rescale <- TRUE
ists <- is.ts(x)
x <- na.action(as.ts(x))
if(anyNA(x)) stop("NAs in 'x'")
if(ists) xtsp <- tsp(x)
xfreq <- frequency(x)
x <- as.matrix(x)
if(!is.numeric(x))
stop("'x' must be numeric")
n.used <- nrow(x)
nser <- ncol(x)
iser <- seq_len(nser)
if(rescale) {
sc <- sqrt(drop(apply(x, 2L, var)))
sc[sc == 0] <- 1
x <- x/rep.int(sc, rep.int(n.used, nser))
} else sc <- rep.int(1, nser)
order.max <- if (is.null(order.max))
min(n.used-1L, floor(10 * log10(n.used))) else round(order.max)
if (order.max < 0L) stop("'order.max' must be >= 0")
if (order.max >= n.used) stop("'order.max' must be < 'n.used'")
order.min <- if (aic) 0L else order.max
varE <- seA <- A <- vector("list", order.max - order.min + 1L)
xaic <- rep.int(Inf, order.max - order.min + 1L)
## allow for rounding error
det <- function(x) max(0, prod(diag(qr(x)$qr))*(-1)^(ncol(x)-1))
## remove means for conditioning
if(demean) {
xm <- colMeans(x)
x <- sweep(x, 2L, xm, check.margin=FALSE)
} else xm <- rep.int(0, nser)
## Fit models of increasing order
for (m in order.min:order.max)
{
y <- embed(x, m+1L)
X <-
if(intercept) {
if(m) cbind(rep.int(1,nrow(y)), y[, (nser+1L):ncol(y)])
else as.matrix(rep.int(1, nrow(y)))
} else {
if(m) y[, (nser+1L):ncol(y)] else matrix(0, nrow(y), 0)
}
## FIXME: use [t]crossprod(); and instead of solve(XX), use solve(qr(X)) !!
Y <- t(y[, iser])
N <- ncol(Y)
XX <- t(X)%*%X
rank <- qr(XX)$rank
if (rank != nrow(XX))
{
warning(paste("model order: ", m,
"singularities in the computation of the projection matrix",
"results are only valid up to model order", m - 1L),
domain = NA)
break
}
P <- if(ncol(XX) > 0) solve(XX) else XX
A[[m - order.min + 1L]] <- Y %*% X %*% P
YH <- A[[m - order.min + 1L]] %*% t(X)
E <- (Y - YH)
varE[[m - order.min + 1L]] <- tcrossprod(E)/N
varA <- P %x% (varE[[m - order.min + 1L]])
seA[[m - order.min+1L]] <-
if(ncol(varA) > 0) sqrt(diag(varA)) else numeric()
xaic[m - order.min+1L] <-
n.used*log(det(varE[[m-order.min+1L]])) + 2*nser*(nser*m+intercept)
}
# Determine best model
m <- if(aic) which.max(xaic == min(xaic)) + order.min - 1L else order.max
## Recalculate residuals of best model
y <- embed(x, m+1L)
AA <- A[[m - order.min + 1L]]
if(intercept) {
xint <- AA[, 1L]
ar <- AA[, -1L]
X <- if(m) cbind(rep.int(1,nrow(y)), y[, (nser+1L):ncol(y)])
else as.matrix(rep.int(1, nrow(y)))
} else {
X <- if(m) y[, (nser+1L):ncol(y)] else matrix(0, nrow(y), 0L)
xint <- NULL
ar <- AA
}
Y <- t(y[, iser, drop = FALSE])
YH <- AA %*% t(X)
E <- drop(rbind(matrix(NA, m, nser), t(Y - YH)))
maic <- min(aic)
xaic <- setNames(if(is.finite(maic)) xaic - min(xaic) else
ifelse(xaic == maic, 0, Inf), order.min:order.max)
dim(ar) <- c(nser, nser, m)
ar <- aperm(ar, c(3L,1L,2L))
ses <- seA[[m - order.min + 1L]]
if(intercept) {
sem <- ses[iser]
ses <- ses[-iser]
} else sem <- rep.int(0, nser)
dim(ses) <- c(nser, nser, m)
ses <- aperm(ses, c(3L,1L,2L))
var.pred <- varE[[m - order.min + 1L]]
if(nser > 1L) {
snames <- colnames(x)
dimnames(ses) <- dimnames(ar) <- list(seq_len(m), snames, snames)
dimnames(var.pred) <- list(snames, snames)
names(sem) <- colnames(E) <- snames
} else {
var.pred <- drop(var.pred)
}
if(ists) {
attr(E, "tsp") <- xtsp
attr(E, "class") <- "ts"
}
if(rescale) {
xm <- xm * sc
if(!is.null(xint)) xint <- xint * sc
aa <- outer(sc, 1/sc)
if(nser > 1L && m) for(i in seq_len(m)) ar[i,,] <- ar[i,,]*aa
var.pred <- var.pred * drop(outer(sc, sc))
E <- E * rep.int(sc, rep.int(NROW(E), nser))
sem <- sem*sc
if(m)
for(i in seq_len(m)) ses[i,,] <- ses[i,,]*aa
}
res <- list(order = m, ar = ar, var.pred = var.pred,
x.mean = xm, x.intercept = xint, aic = xaic,
n.used = n.used, n.obs = n.used, order.max = order.max,
partialacf = NULL, resid = E, method = "Unconstrained LS",
series = series, frequency = xfreq, call = match.call(),
asy.se.coef = list(x.mean = sem, ar = drop(ses)))
class(res) <- "ar"
res
}
ar.yw.mts <-
function (x, aic = TRUE, order.max = NULL, na.action = na.fail,
demean = TRUE, series = NULL, var.method = 1L, ...)
{
if (is.null(series)) series <- deparse(substitute(x))
if (ists <- is.ts(x)) xtsp <- tsp(x)
x <- na.action(as.ts(x))
if(any(is.na(x) != is.na(x[,1]))) stop("NAs in 'x' must be the same row-wise")
if (ists) xtsp <- tsp(x)
xfreq <- frequency(x)
x <- as.matrix(x)
nser <- ncol(x)
n.used <- nrow(x)
n.obs <- sum(!is.na(x[,1])) # number of non-missing rows
if (demean) {
x.mean <- colMeans(x, na.rm=TRUE)
x <- sweep(x, 2L, x.mean, check.margin=FALSE)
}
else x.mean <- rep(0, nser)
order.max <- floor(if(is.null(order.max)) 10 * log10(n.obs) else order.max)
if (order.max < 1L)
stop("'order.max' must be >= 1")
xacf <- acf(x, type = "cov", plot = FALSE,
lag.max = order.max, na.action = na.pass)$acf
z <- .C(C_multi_yw,
aperm(xacf, 3:1),
as.integer(n.obs),
as.integer(order.max),
as.integer(nser),
coefs = double((1L + order.max) * nser * nser),
pacf = double((1L + order.max) * nser * nser),
var = double((1L + order.max) * nser * nser),
aic = double(1L + order.max),
order = integer(1L),
as.integer(aic))
partialacf <- aperm(array(z$pacf, dim = c(nser, nser, order.max + 1L)), 3:1)[-1L, , , drop = FALSE]
var.pred <- aperm(array(z$var, dim = c(nser, nser, order.max + 1L)), 3:1)
xaic <- setNames(z$aic - min(z$aic), 0:order.max)
order <- z$order
resid <- x
if (order > 0) {
ar <- -aperm(array(z$coefs, dim = c(nser, nser, order.max + 1L)), 3:1)[2L:(order + 1L), , , drop = FALSE]
for (i in 1L:order)
resid[-(1L:order), ] <- resid[-(1L:order),] - x[(order - i + 1L):(n.used - i), ] %*% t(ar[i, , ])
resid[1L:order, ] <- NA
}
else ar <- array(dim = c(0, nser, nser))
var.pred <- var.pred[order + 1L, , , drop = TRUE] * n.obs/(n.obs - nser * (demean + order))
if (ists) {
attr(resid, "tsp") <- xtsp
attr(resid, "class") <- c("mts", "ts")
}
snames <- colnames(x)
colnames(resid) <- snames
dimnames(ar) <- list(seq_len(order), snames, snames)
dimnames(var.pred) <- list(snames, snames)
dimnames(partialacf) <- list(1L:order.max, snames, snames)
res <- list(order = order, ar = ar, var.pred = var.pred,
x.mean = x.mean, aic = xaic, n.used = n.used, n.obs = n.obs, order.max = order.max,
partialacf = partialacf, resid = resid, method = "Yule-Walker",
series = series, frequency = xfreq, call = match.call())
class(res) <- "ar"
res
}
## ar.burg by B.D. Ripley based on R version by Martyn Plummer
ar.burg <- function(x, ...) UseMethod("ar.burg")
ar.burg.default <-
function (x, aic = TRUE, order.max = NULL, na.action = na.fail,
demean = TRUE, series = NULL, var.method = 1L, ...)
{
if(is.null(series)) series <- deparse(substitute(x))
if (ists <- is.ts(x)) xtsp <- tsp(x)
x <- na.action(as.ts(x))
if(anyNA(x)) stop("NAs in 'x'")
if (ists) xtsp <- tsp(x)
xfreq <- frequency(x)
x <- as.vector(x) # drop attributes including class
if (demean) {
x.mean <- mean(x)
x <- x - x.mean
} else x.mean <- 0
n.used <- length(x)
order.max <- if (is.null(order.max))
min(n.used-1L, floor(10 * log10(n.used)))
else floor(order.max)
if (order.max < 1L) stop("'order.max' must be >= 1")
else if (order.max >= n.used) stop("'order.max' must be < 'n.used'")
xaic <- numeric(order.max + 1L)
z <- .Call(C_Burg, x, order.max)
coefs <- matrix(z[[1L]], order.max, order.max)
partialacf <- array(diag(coefs), dim = c(order.max, 1L, 1L))
var.pred <- if(var.method == 1L) z[[2L]] else z[[3L]]
if (any(is.nan(var.pred))) stop("zero-variance series")
xaic <- n.used * log(var.pred) + 2 * (0L:order.max) + 2 * demean
maic <- min(aic)
xaic <- setNames(if(is.finite(maic)) xaic - min(xaic) else
ifelse(xaic == maic, 0, Inf), 0L:order.max)
order <- if (aic) (0L:order.max)[xaic == 0] else order.max
ar <- if (order) coefs[order, 1L:order] else numeric()
var.pred <- var.pred[order + 1L]
resid <- if(order) c(rep(NA, order), embed(x, order+1L) %*% c(1, -ar))
else x
if(ists) {
attr(resid, "tsp") <- xtsp
attr(resid, "class") <- "ts"
}
res <- list(order = order, ar = ar, var.pred = var.pred, x.mean = x.mean,
aic = xaic, n.used = n.used, n.obs = n.used, order.max = order.max,
partialacf = partialacf, resid = resid,
method = ifelse(var.method==1L,"Burg","Burg2"),
series = series, frequency = xfreq, call = match.call())
if(order) {
xacf <- acf(x, type = "covariance", lag.max = order, plot = FALSE)$acf
res$asy.var.coef <- solve(toeplitz(drop(xacf)[seq_len(order)]))*var.pred/n.used
}
class(res) <- "ar"
res
}
ar.burg.mts <-
function (x, aic = TRUE, order.max = NULL, na.action = na.fail,
demean = TRUE, series = NULL, var.method = 1L, ...)
{
if (is.null(series))
series <- deparse(substitute(x))
if (ists <- is.ts(x))
xtsp <- tsp(x)
x <- na.action(as.ts(x))
if (anyNA(x))
stop("NAs in 'x'")
if (ists)
xtsp <- tsp(x)
xfreq <- frequency(x)
x <- as.matrix(x)
nser <- ncol(x)
n.used <- nrow(x)
if (demean) {
x.mean <- colMeans(x)
x <- sweep(x, 2L, x.mean, check.margin = FALSE)
}
else x.mean <- rep(0, nser)
order.max <- floor(if(is.null(order.max)) 10 * log10(n.used) else order.max)
z <- .C(C_multi_burg,
as.integer(n.used),
resid = as.double(x),
as.integer(order.max),
as.integer(nser),
coefs = double((1L + order.max) * nser * nser),
pacf = double((1L + order.max) * nser * nser),
var = double((1L + order.max) * nser * nser),
aic = double(1L + order.max),
order = integer(1L),
as.integer(aic),
as.integer(var.method))
partialacf <-
aperm(array(z$pacf, dim = c(nser, nser, order.max + 1L)), 3:1)[-1L, , , drop = FALSE]
var.pred <- aperm(array(z$var, dim = c(nser, nser, order.max + 1L)), 3:1)
xaic <- setNames(z$aic - min(z$aic), 0:order.max)
order <- z$order
ar <- if (order)
-aperm(array(z$coefs, dim = c(nser, nser, order.max + 1L)), 3:1)[2L:(order + 1L), , , drop = FALSE]
else array(dim = c(0, nser, nser))
var.pred <- var.pred[order + 1L, , , drop = TRUE]
resid <- matrix(z$resid, nrow = n.used, ncol = nser)
if (order) resid[seq_len(order), ] <- NA
if (ists) {
attr(resid, "tsp") <- xtsp
attr(resid, "class") <- "mts"
}
snames <- colnames(x)
colnames(resid) <- snames
dimnames(ar) <- list(seq_len(order), snames, snames)
dimnames(var.pred) <- list(snames, snames)
dimnames(partialacf) <- list(seq_len(order.max), snames, snames)
res <- list(order = order, ar = ar, var.pred = var.pred, x.mean = x.mean,
aic = xaic, n.used = n.used, n.obs = n.used, order.max = order.max,
partialacf = partialacf, resid = resid,
method = ifelse(var.method == 1L, "Burg", "Burg2"),
series = series, frequency = xfreq,
call = match.call())
class(res) <- "ar"
res
}