# TODO: could use source code of C_acf and adjust for panel: https://github.com/SurajGupta/r-source/blob/a28e609e72ed7c47f6ddfbb86c85279a0750f0b7/src/library/stats/src/filter.c
psacf <- function(x, ...) UseMethod("psacf") # , x
psacf.default <- function(x, g, t = NULL, lag.max = NULL, type = c("correlation", "covariance","partial"), plot = TRUE, gscale = TRUE, ...) {
if(!is.numeric(x)) stop("'x' must be a numeric vector")
typei <- switch(type[1L], correlation = 1L, covariance = 2L, partial = 3L, stop("Unknown type!"))
series <- l1orlst(as.character(substitute(x)))
g <- G_guo(g)
if(is.null(lag.max)) lag.max <- round(2*sqrt(length(x)/g[[1L]]))
if(gscale) x <- fscaleCpp(x,g[[1L]],g[[2L]])
acf <- if(typei == 2L)
cov(x, .Call(Cpp_flaglead,x,0:lag.max,NA,g[[1L]],g[[2L]],G_t(t),FALSE), use = "pairwise.complete.obs") else
c(1, cov(x, .Call(Cpp_flaglead,x,seq_len(lag.max),NA,g[[1L]],g[[2L]],G_t(t),FALSE), use = "pairwise.complete.obs")/fvar.default(x)) # or complete obs ?
d <- c(lag.max+1,1,1)
if(typei == 3L) {
acf <- .Call(C_pacf1, array(acf, d), lag.max)
lag <- array(seq_len(d[1]), c(lag.max,1,1))
} else {
dim(acf) <- d
lag <- array(0:lag.max, d)
}
acf.out <- `oldClass<-`(list(acf = acf, type = type[1L], n.used = length(x), lag = lag, series = series, snames = NULL), "acf")
if(plot) {
plot(acf.out, ylab = if(typei == 3L) "Panel Series Partial ACF" else "Panel Series ACF", ...)
invisible(acf.out)
} else {
if(!missing(...)) unused_arg_action(match.call(), ...)
return(acf.out)
}
}
psacf.data.frame <- function(x, by, t = NULL, cols = is.numeric, lag.max = NULL, type = c("correlation", "covariance","partial"), plot = TRUE, gscale = TRUE, ...) {
typei <- switch(type[1L], correlation = 1L, covariance = 2L, partial = 3L, stop("Unknown type!"))
series <- l1orlst(as.character(substitute(x)))
oldClass(x) <- NULL
if(is.call(by)) { # best way ?
nam <- names(x)
if(length(by) == 3L) {
v <- ckmatch(all.vars(by[[2L]]), nam)
by <- ckmatch(all.vars(by[[3L]]), nam)
} else {
by <- ckmatch(all.vars(by), nam)
v <- if(is.null(cols)) seq_along(x)[-by] else fsetdiff(cols2int(cols, x, nam), by)
}
by <- if(length(by) == 1L) x[[by]] else x[by]
if(is.call(t)) { # If time-variable supplied
tv <- ckmatch(all.vars(t), nam, "Unknown time variable:")
v <- fsetdiff(v, tv)
t <- eval(if(length(tv) == 1L) t[[2L]] else attr(terms.formula(t), "variables"), x, attr(t, ".Environment")) # if(length(t) == 1L) x[[t]] else x[t]
}
x <- x[v]
} else if(length(cols)) x <- x[cols2int(cols, x, names(x), FALSE)]
lx <- length(x)
nrx <- .Call(C_fnrow, x)
snames <- names(x)
attributes(x) <- NULL # already class is 0... Necessary ?
getacf <- function(ng, g) {
if(length(t)) t <- G_t(t)
if(gscale) x <- fscalelCpp(x,ng,g)
acf <- array(numeric(0), c(lag.max+1, lx, lx))
fun <- if(typei == 2L) cov else function(x, y, ...) cov(x, y, ...)/fvar.default(x) # cor
for(i in seq_len(lx)) {
xim <- .Call(Cpp_flaglead,x[[i]],0:lag.max,NA,ng,g,t,FALSE)
for(j in seq_len(lx)) acf[ , j, i] <- fun(x[[j]], xim, use = "pairwise.complete.obs") # correct !
}
acf
}
by <- G_guo(by)
if(is.null(lag.max)) lag.max <- round(2*sqrt(nrx/by[[1L]]))
acf <- getacf(by[[1L]], by[[2L]])
lag <- matrix(1, lx, lx)
lag[lower.tri(lag)] <- -1
if(typei == 3L) {
zvec <- double((1L+lag.max)*lx*lx)
z <- .C(C_multi_yw, aperm(acf, 3:1), as.integer(nrx), as.integer(lag.max), as.integer(lx),
coefs = zvec, pacf = zvec, var = zvec, aic = double(1L+lag.max), order = 0L, 1L)
acf <- aperm(array(z$pacf, dim = c(lx, lx, lag.max + 1L)), 3:1)[-1L, , , drop = FALSE]
}
acf.out <- `oldClass<-`(list(acf = acf, type = type[1L], n.used = nrx,
lag = if(typei == 3L) outer(1L:lag.max, lag) else outer(0L:lag.max, lag),
series = series, snames = snames), "acf")
if(plot) {
plot(acf.out, ylab = if(typei == 3L) "Panel Series Partial ACF" else "Panel Series ACF",
mar = if(lx > 2) c(3, 2.4, 2, 0.8) else par("mar"), ...)
invisible(acf.out)
} else {
if(!missing(...)) unused_arg_action(match.call(), ...)
return(acf.out)
}
}
psacf.pseries <- function(x, lag.max = NULL, type = c("correlation", "covariance","partial"), plot = TRUE, gscale = TRUE, ...) {
if(!is.numeric(x)) stop("'x' must be a numeric pseries ")
index <- uncl2pix(x)
g <- index[[1L]]
t <- index[[2L]]
if(length(t) && !inherits(x, "indexed_series")) t <- plm_check_time(t)
ng <- fnlevels(g)
typei <- switch(type[1L], correlation = 1L, covariance = 2L, partial = 3L, stop("Unknown type!"))
series <- l1orlst(as.character(substitute(x))) # faster ?
if(is.null(lag.max)) lag.max <- round(2*sqrt(length(x)/ng))
if(gscale) x <- fscaleCpp(x,ng,g)
acf <- if(typei == 2L)
cov(x, .Call(Cpp_flaglead,x,0:lag.max,NA,ng,g,t,FALSE), use = "pairwise.complete.obs") else
c(1, cov(x, .Call(Cpp_flaglead,x,seq_len(lag.max),NA,ng,g,t,FALSE), use = "pairwise.complete.obs")/fvar.default(x)) # or complete obs ?
d <- c(lag.max+1,1,1)
if(typei == 3L) {
acf <- .Call(C_pacf1, array(acf, d), lag.max)
lag <- array(seq_len(d[1]), c(lag.max,1,1))
} else {
dim(acf) <- d
lag <- array(0:lag.max, d)
}
acf.out <- `oldClass<-`(list(acf = acf, type = type[1L], n.used = length(x), lag = lag, series = series, snames = NULL), "acf")
if (plot) {
plot(acf.out, ylab = if(typei == 3L) "Panel Series Partial ACF" else "Panel Series ACF", ...)
invisible(acf.out)
} else {
if(!missing(...)) unused_arg_action(match.call(), ...)
return(acf.out)
}
}
psacf.pdata.frame <- function(x, cols = is.numeric, lag.max = NULL, type = c("correlation", "covariance","partial"), plot = TRUE, gscale = TRUE, ...) {
typei <- switch(type[1L], correlation = 1L, covariance = 2L, partial = 3L, stop("Unknown type!"))
series <- l1orlst(as.character(substitute(x))) # faster solution ?
index <- uncl2pix(x)
clx <- oldClass(x)
oldClass(x) <- NULL
nrx <- .Call(C_fnrow, x)
if(length(cols)) x <- x[cols2int(cols, x, names(x), FALSE)]
lx <- length(x)
snames <- names(x)
g <- index[[1L]]
t <- index[[2L]]
if(length(t) && !any(clx == "indexed_frame")) t <- plm_check_time(t)
ng <- fnlevels(g)
attributes(x) <- NULL # necessary after unclass above ?
if(is.null(lag.max)) lag.max <- round(2*sqrt(nrx/ng))
if(gscale) x <- fscalelCpp(x,ng,g)
acf <- array(numeric(0), c(lag.max+1, lx, lx))
fun <- if(typei == 2L) cov else function(x, y, ...) cov(x, y, ...)/fvar.default(x) # cor
for(i in seq_len(lx)) {
xim <- .Call(Cpp_flaglead,x[[i]],0:lag.max,NA,ng,g,t,FALSE)
for(j in seq_len(lx)) acf[ , j, i] <- fun(x[[j]], xim, use = "pairwise.complete.obs") # correct !
}
lag <- matrix(1, lx, lx)
lag[lower.tri(lag)] <- -1
if(typei == 3L) {
zvec <- double((1L+lag.max)*lx*lx)
z <- .C(C_multi_yw, aperm(acf, 3:1), as.integer(nrx), as.integer(lag.max), as.integer(lx),
coefs = zvec, pacf = zvec, var = zvec, aic = double(1L+lag.max), order = 0L, 1L)
acf <- aperm(array(z$pacf, dim = c(lx, lx, lag.max + 1L)), 3:1)[-1L, , , drop = FALSE]
}
acf.out <- `oldClass<-`(list(acf = acf, type = type[1L], n.used = nrx,
lag = if(typei == 3L) outer(1L:lag.max, lag) else outer(0L:lag.max, lag),
series = series, snames = snames), "acf")
if(plot) {
plot(acf.out, ylab = if(typei == 3L) "Panel Series Partial ACF" else "Panel Series ACF",
mar = if(lx > 2) c(3, 2.4, 2, 0.8) else par("mar"), ...)
invisible(acf.out)
} else {
if(!missing(...)) unused_arg_action(match.call(), ...)
return(acf.out)
}
}
pspacf <- function(x, ...) UseMethod("pspacf") # , x
pspacf.default <- function(x, g, t = NULL, lag.max = NULL, plot = TRUE, gscale = TRUE, ...) {
if(plot)
psacf.default(x, g, t, lag.max, "partial", plot, gscale, main = paste0("Series ",l1orlst(as.character(substitute(x)))), ...) else
psacf.default(x, g, t, lag.max, "partial", plot, gscale, ...)
}
pspacf.pseries <- function(x, lag.max = NULL, plot = TRUE, gscale = TRUE, ...) {
if(plot)
psacf.pseries(x, lag.max, "partial", plot, gscale, main = paste0("Series ",l1orlst(as.character(substitute(x)))), ...) else
psacf.pseries(x, lag.max, "partial", plot, gscale, ...)
}
pspacf.data.frame <- function(x, by, t = NULL, cols = is.numeric, lag.max = NULL, plot = TRUE, gscale = TRUE, ...) {
psacf.data.frame(x, by, t, cols, lag.max, "partial", plot, gscale, ...)
}
pspacf.pdata.frame <- function(x, cols = is.numeric, lag.max = NULL, plot = TRUE, gscale = TRUE, ...) {
psacf.pdata.frame(x, cols, lag.max, "partial", plot, gscale, ...)
}
psccf <- function(x, y, ...) UseMethod("psccf") # , x
psccf.default <- function(x, y, g, t = NULL, lag.max = NULL, type = c("correlation", "covariance"), plot = TRUE, gscale = TRUE, ...) {
if(!is.numeric(x)) stop("'x' must be a numeric vector")
if(!is.numeric(y)) stop("'y' must be a numeric vector")
lx <- length(x)
if(lx != length(y)) stop("length(x) must be equal to length(y)")
typei <- switch(type[1L], correlation = 1L, covariance = 2L, partial = 3L, stop("Unknown type!"))
snames <- paste(c(l1orlst(as.character(substitute(x))), l1orlst(as.character(substitute(x)))), collapse = " & ")
getccf <- function(ng, g) {
if(length(t)) t <- G_t(t)
if(gscale) {
x <- fscaleCpp(x,ng,g)
y <- fscaleCpp(y,ng,g)
}
if(typei == 2L)
drop(cov(x, .Call(Cpp_flaglead,y,-lag.max:lag.max,NA,ng,g,t,FALSE), use = "pairwise.complete.obs")) else
drop(cov(x, .Call(Cpp_flaglead,y,-lag.max:lag.max,NA,ng,g,t,FALSE), use = "pairwise.complete.obs")/(fsd.default(x)*fsd.default(y))) # or complete obs ?
}
g <- G_guo(g)
if(is.null(lag.max)) lag.max <- round(2*sqrt(lx/g[[1L]]))
acf <- getccf(g[[1L]], g[[2L]])
d <- c(2*lag.max+1,1,1)
dim(acf) <- d
acf.out <- `oldClass<-`(list(acf = acf, type = type[1L], n.used = lx,
lag = array(-lag.max:lag.max, d), series = snames, snames = snames), "acf")
if (plot) {
plot(acf.out, ylab = "Panel Series CCF", ...)
invisible(acf.out)
} else {
if(!missing(...)) unused_arg_action(match.call(), ...)
return(acf.out)
}
}
psccf.pseries <- function(x, y, lag.max = NULL, type = c("correlation", "covariance"), plot = TRUE, gscale = TRUE, ...) {
if(!is.numeric(x)) stop("'x' must be a numeric pseries")
if(!is.numeric(y) || !inherits(y, "pseries")) stop("'y' must be a numeric pseries")
lx <- length(x)
if(lx != length(y)) stop("length(x) must be equal to length(y)")
if(!identical(findex(x), findex(y))) stop("index of x and y differs")
index <- uncl2pix(x)
g <- index[[1L]]
t <- index[[2L]]
if(length(t) && !inherits(x, "indexed_series")) t <- plm_check_time(t)
ng <- fnlevels(g)
typei <- switch(type[1L], correlation = 1L, covariance = 2L, partial = 3L, stop("Unknown type!"))
snames <- paste(c(l1orlst(as.character(substitute(x))), l1orlst(as.character(substitute(x)))), collapse = " & ")
if (gscale) {
x <- fscaleCpp(x,ng,g)
y <- fscaleCpp(y,ng,g)
}
if (is.null(lag.max)) lag.max <- round(2*sqrt(length(x)/ng))
l_seq <- -lag.max:lag.max
acf <- if(typei == 2L)
drop(cov(x, .Call(Cpp_flaglead,y,l_seq,NA,ng,g,t,FALSE), use = "pairwise.complete.obs")) else
drop(cov(x, .Call(Cpp_flaglead,y,l_seq,NA,ng,g,t,FALSE), use = "pairwise.complete.obs")/(fsd.default(x)*fsd.default(y))) # or complete obs ?
d <- c(2*lag.max+1,1,1)
dim(acf) <- d
acf.out <- `oldClass<-`(list(acf = acf, type = type[1L], n.used = lx,
lag = array(l_seq, d), series = snames, snames = snames), "acf")
if (plot) {
plot(acf.out, ylab = "Panel Series CCF", ...)
invisible(acf.out)
} else {
if(!missing(...)) unused_arg_action(match.call(), ...)
return(acf.out)
}
}
# could do AR models also :
# psar.data.frame <- function (x, aic = TRUE, order.max = lag.max, na.action = na.fail,
# demean = TRUE, series = NULL, var.method = 1L, ...)
# {
# if (is.null(series))
# series <- l1orlst(as.character(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 <- if (is.null(order.max))
# floor(10 * log10(n.used))
# else floor(order.max)
# if (order.max < 1L)
# stop("'order.max' must be >= 1")
# xacf <- acf(x, type = "cov", plot = FALSE, lag.max = order.max)$acf
# z <- .C(stats:::C_"multi_yw",
# aperm(xacf, 3:1),
# as.integer(n.used),
# 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 - bmin(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.used/(n.used -
# 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, order.max = order.max,
# partialacf = partialacf, resid = resid, method = "Yule-Walker",
# series = series, frequency = xfreq, call = match.call())
# oldClass(res) <- "ar"
# return(res)
# }
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.