由于需要批量为各种时间序列定阶,所以搜到了这个问题,2024-11-10 的今天,我尝试回答这个2017年的问题。
R中的acf与pacf函数均可查看源代码:
acf的源代码可在R控制台直接键入acf+回车查看:
function (x, lag.max = NULL, type = c("correlation", "covariance",
"partial"), plot = TRUE, na.action = na.fail, demean = TRUE,
...)
{
......
......
acf.out <- structure(list(acf = acf, type = type, n.used = sampleT,
lag = lag, series = series, snames = colnames(x)), class = "acf")
if (plot) {
plot.acf(acf.out, ...)
invisible(acf.out)
}
else acf.out
}
而pacf的源代码查看起来有些费劲,如果直接输入pacf+回车,系统会提示UseMethod("pacf"),如果直接输入methods(pacf),则会提示pacf.default*。
直到运用getAnywhere(pacf.default)命令,才最终获得了pacf的代码:
function (x, lag.max = NULL, plot = TRUE, na.action = na.fail,
...)
{
......
......
acf.out <- structure(.Data = list(acf = pacf, type = "partial",
n.used = sampleT, lag = lag, series = series, snames = snames),
class = "acf")
if (plot) {
plot.acf(acf.out, ...)
invisible(acf.out)
}
else acf.out
}
通过acf与pacf代码可知,两者返回的结果均是结构体(structure),我的第一反应是:能否用一个变量承接acf或pacf的结果,再在这个结果中寻找“上下虚线界限”的具体值。
于是测试如下:
> a = rnorm(100)
> b1 = acf(a, plot = FALSE)
> b2 = pacf(a, plot = FALSE)
> names(b1)
[1] "acf" "type" "n.used" "lag" "series" "snames"
> names(b2)
[1] "acf" "type" "n.used" "lag" "series" "snames"
> b1$type
[1] "correlation"
> b2$type
[1] "partial"
> b1$n.used
[1] 100
> b2$n.used
[1] 100
......
......
很抱歉,经过测试,acf与pacf函数的结果中,并不包含“上下虚线界限”的具体值。
只能再次回到acf与pacf函数的代码中,两函数在最后都有语句——plot.acf(acf.out, ...)
所以,系统产生“上下虚线界限”的具体值的过程必然在plot.acf函数中。
在R控制台中,输入getAnywhere(plot.acf)命令可以查看plot.acf函数的源代码:
function (x, ci = 0.95, type = "h", xlab = "Lag", ylab = NULL,
ylim = NULL, main = NULL, ci.col = "blue", ci.type = c("white",
"ma"), max.mfrow = 6, ask = Npgs > 1 && dev.interactive(),
mar = if (nser > 2) c(3, 2, 2, 0.8) else par("mar"), oma = if (nser >
2) c(1, 1.2, 1, 1) else par("oma"), mgp = if (nser >
2) c(1.5, 0.6, 0) else par("mgp"), xpd = par("xpd"),
cex.main = if (nser > 2) 1 else par("cex.main"), verbose = getOption("verbose"),
...)
{
ci.type <- match.arg(ci.type)
......
with.ci <- ci > 0 && x$type != "covariance"
with.ci.ma <- with.ci && ci.type == "ma" && x$type == "correlation"
......
clim0 <- if (with.ci)
qnorm((1 + ci)/2)/sqrt(x$n.used)
else c(0, 0)
......
for (I in 1L:Npgs) for (J in 1L:Npgs) {
......
if (verbose)
......
}
else {
clim <- if (with.ci.ma && i == j)
clim0 * sqrt(cumsum(c(1, 2 * x$acf[-1, i, j]^2)))
else clim0
plot(......)
abline(h = 0)
if (with.ci && ci.type == "white")
abline(h = c(clim, -clim), col = ci.col, lty = 2)
else if (with.ci.ma && i == j) {
......
}
......
}
......
}
invisible()
}
先寻找绘制虚线的语句:
abline(h = c(clim, -clim), col = ci.col, lty = 2)
很好,其中的clim就是虚线正值,于是再寻找clim如何产生,找到如下语句:
clim <- if (with.ci.ma && i == j)
clim0 * sqrt(cumsum(c(1, 2 * x$acf[-1, i, j]^2)))
else clim0
放弃对 clim0 * sqrt(cumsum(c(1, 2 * x$acf[-1, i, j]^2))) 的思考,因为它太复杂,直觉判断实际生成的虚线没有这么复杂。
于是我将精力集中在 clim0 上,它才是大多数情况下 clim 的实际数值。
于是接着寻找 clim0 代表的实际数值,找到如下语句:
clim0 <- if (with.ci)
qnorm((1 + ci)/2)/sqrt(x$n.used)
else c(0, 0)
准确来说,clim0的值就是 —— qnorm((1 + ci)/2)/sqrt(x$n.used)
也就是说,“上虚线界限”的值就是 qnorm((1 + ci)/2)/sqrt(x$n.used)
ci 是啥?查看 plot.acf 的第一行代码可知,它等于0.95
(1 + ci)/2 等于多少?0.975
qnorm((1 + ci)/2) 是啥?标准正态分布的累积分布函数 F(x) = Pr(X <= x) = p = 0.975,这里的 x 就是qnorm((1 + ci)/2)的值。
x$n.used 又是啥?从前面测试acf与pacf函数结果的几句命令的反馈来看,这里的 x$n.used 指的是时间序列的样本容量。
我不是数学专业或统计专业毕业,所以无法回答为什么虚线上限(加负号就是下限)是这个样子的,但是R的开源属性让我知道它就是这个样子的。