如何计算 xts 中行之间的滚动相关性?

How to calculate rolling correlation between rows in an xts?

我有 xts 的年度数据。我试图获得每年之间的排名相关性。例如,这是我的 xts 的一个子集:

> yearlyRanks[16:20,45:55]
           35881 35880 42261 33445 46087 31486 8981 7687 8203 8202 41383
2009-12-31     8     9    19     8    18    18   16    4   16   16    20
2010-12-31     4     3    20     6    19     2   17   17   17   17    21
2011-12-31     3     4    21     3    20     1   18   18   18   18    22
2012-12-31     6     6    22     5    21    19   19   19   19   19     4
2013-12-31     7     7     3     4    22    20   20   20   20   20     2

我想知道每一年的排名与前一年的相关性。 (试图判断今年的排名与去年的预测有多好。)

我正在尝试使用这个:

yearlyCors <- rollapplyr(coredata(yearlyRanks), width = 2, function(x) cor(x[1], x[2], use = 'n'))

但这需要很长时间,而且似乎不起作用。我认为这是因为我向它传递了一组 2 行,所以它想要 return 2 个值,但我只期望 1 个。(这有意义吗?)

关于我将如何做到这一点有什么想法吗?

编辑:

需要说明的是,这就是我希望从该子集中得到的:

> test <- yearlyRanks[16:20,45:55]
> c(cor(test[1,], test[2,]), cor(test[2,], test[3,]), cor(test[3,], test[4,]), cor(test[4,], test[5,]))
[1] 0.4679246 0.9930253 0.4854528 0.7193598

编辑:

我要的是相关矩阵的diag() + 1。这是(转置的)相关矩阵:

> cor(t(test))
           2009-12-31 2010-12-31 2011-12-31 2012-12-31 2013-12-31
2009-12-31 1.00000000  *0.4679246*  0.4716995  0.3722922 0.08786426
2010-12-31 0.46792463  1.0000000  *0.9930253*  0.4654688 0.17192856
2011-12-31 0.47169948  0.9930253  1.0000000  *0.4854528* 0.20237689
2012-12-31 0.37229225  0.4654688  0.4854528  1.0000000 *0.71935975*
2013-12-31 0.08786426  0.1719286  0.2023769  0.7193598 1.00000000

你可以看到加星标的值就是我想要的。有没有办法访问 diag + 1(如果你遵循)?

我想我明白了。我只是从转置的相关矩阵中取出第一列,然后进行诊断:

> test <- yearlyRanks[16:20,45:55]
> tester <- cor(t(test), use = 'p')
> tester
           2009-12-31 2010-12-31 2011-12-31 2012-12-31 2013-12-31
2009-12-31  1.0000000  0.6309825  0.6167215  0.7106686  0.6076932
2010-12-31  0.6309825  1.0000000  0.9799418  0.4088352  0.2449624
2011-12-31  0.6167215  0.9799418  1.0000000  0.3973902  0.2471984
2012-12-31  0.7106686  0.4088352  0.3973902  1.0000000  0.7315524
2013-12-31  0.6076932  0.2449624  0.2471984  0.7315524  1.0000000
> xts(diag(tester[,-1]), order.by = as.Date(rownames(test))[-1])
                [,1]
2010-12-31 0.6309825
2011-12-31 0.9799418
2012-12-31 0.3973902
2013-12-31 0.7315524

但是,我认为这不是最好的方法,因为它看起来效率很低。我正在计算一堆我不需要的相关性。它非常快,但是如果有人想要 post 更有效的解决方案,请做!

(抱歉,值已更改。我之前做错了,但不用担心!你们都应该明白要点!)

这是您获得所需结果的一种方式:

data <- "35881 35880 42261 33445 46087 31486 8981 7687 8203 8202 41383
2009-12-31     8     9    19     8    18    18   16    4   16   16    20
2010-12-31     4     3    20     6    19     2   17   17   17   17    21
2011-12-31     3     4    21     3    20     1   18   18   18   18    22
2012-12-31     6     6    22     5    21    19   19   19   19   19     4
2013-12-31     7     7     3     4    22    20   20   20   20   20     2"
dat <- read.table(text = data)
yearlyRanks <- xts(dat, order.by = as.POSIXct(row.names(dat)))

m_yearlyRanks <- t(coredata(yearlyRanks))
unlist(lapply(1:(NCOL(m_yearlyRanks) -1), function(i, x) cor(x[,i], x[, i + 1]), x = m_yearlyRanks))
# > unlist(lapply(1:(NCOL(m_yearlyRanks) -1), function(i, x) cor(x[,i], x[, i + 1]), x = m_yearlyRanks))
# [1] 0.4679246 0.9930253 0.4854528 0.7193598

最后一行代码读起来可能有点棘手。它可以更详细地表达为(结果相同):

res <- vector("numeric", length = NCOL(m_yearlyRanks) -1)
for (i in 1:(NCOL(m_yearlyRanks) -1)) {
    res[i] <- cor(m_yearlyRanks[,i], m_yearlyRanks[, i + 1])
}
# > res
# [1] 0.4679246 0.9930253 0.4854528 0.7193598

您在这段代码中的错误:

yearlyCors <- rollapplyr(coredata(yearlyRanks), width = 2, function(x) cor(x[1], x[2], use = 'n'))

源于 x 返回一列数据(数字向量),其中 x[1] 和 x[2] 是 x 的元素 1 和 2,然后将其传递到 cor. cor 需要两个数据向量,但每次调用 roll 函数时它都会获得 2 个标量。尝试使用 browser 调试该函数,您会立即清楚问题所在。例如试试打电话:

yearlyCors <- rollapplyr(coredata(GS), width = 20, function(x) {
    browser()
    cor(x[1], x[2], use = 'n')
    }
    )

使用 by.column=FALSE 并确保函数引用行:

cor2 <- function(x) cor(x[1,], x[2,])
rollapplyr(coredata(yearlyRanks), 2, cor2, by.column = FALSE)
## [1] 0.4679246 0.9930253 0.4854528 0.7193598

我们也可以这样做:

z <- rollapplyr(as.zoo(yearlyRanks), 2, cor2, by.column = FALSE)
as.xts(z)

给予:

                [,1]
2010-12-31 0.4679246
2011-12-31 0.9930253
2012-12-31 0.4854528
2013-12-31 0.7193598