【问题标题】:zoo::rollapply does not give the entire run of rolling correlationzoo::rollapply 没有给出滚动相关的整个运行
【发布时间】:2020-11-29 09:57:23
【问题描述】:

我试图做一些体力劳动来计算我自己的滚动 beta 以获得一些股票日志回报,并遇到了这个特殊的问题。 为了真正重现这个问题,我粘贴了我的完整数据集(csv 文件)here

此数据集有一个日期列,但在我进行计算时已将其排除。下面 sn-p 将创建与我实验过的相同的数据集。

library(readr)
library(dplyr)
library(data.table)

test <- read_csv(YOUR_PATH_TO_MY_DATASET) %>%
        select(-date) %>%
        as.data.table

然后我对典型的stats::cor 函数运行滚动应用。

library(zoo)

roll.cor <- rollapplyr(test, 
                      width=50, 
                      function(x) cor(x,
                                      method="spearman"),
                      by.column=F)
            

我的输入列的长度是 1724(我们稍后会提到这个数字。)

现在有趣的地方来了。 我发现rollingapply 只填满了输入矩阵的长度(不包括obs 的第一个width 数字),至少在stats::cor(和corrr::correlate)的情况下。

我的意思是:在我的示例中,我的窗口大小为 50,因此第一个相关性计算将采用矩阵的前 50 个obs。例如test$A[1:50]test$B[1:50] 等等。然后第二个计算将前滚一个ob 并变为test$A[2:51]test$B[2:51] 然后我们有test$A[3:52]test$B[3:52]test$A[4:53]test$B[4:53] 等等。我们可以很容易地证明这一点:

# following results match up with the result we get from rollapply.

cor(testA$[1:50], test$B[1:50], method="spearman")
# 0.6520358
cor(testA$[2:51], test$B[2:51], method="spearman")
# 0.662828385
cor(testA$[3:52], test$B[3:52], method="spearman")
# 0.655938477

由于 stats::cor 函数返回的相关矩阵的行数与变量数一样多,因此每次运行 stats:cor 都会给我 5 行。 rollapplystats:cor 的第 335 次运行时停止,仅仅是因为 335 * 5 = 1675 (1724 - 49 = 1675)。如果我们取出前 50 个obs(包括第一个ob),我们最终得到1675 个obs,而rollapply 决定在达到这个长度后停止。我们见证了这一点,

tail(roll.cor, n=5)
cor(test$A[335:384), test$B[335:384], method="spearman")
# 0.6806554

因此,rollapply 基本上停在了obs 的第 335 位,而 obs 的其余部分就被丢弃了(至少似乎是这样)。

尽管如此,我仍然希望这种滚动机制能够持续到我们达到最后 50 个obs,即test$A[1675:1724]test$B[1675:1724];这样我们就可以得到1675 * 5 = 8375 的行数(回想一下stats::cor 的每次运行都会给出5 行)。

这应该是rollingR 中的工作方式吗?或者这是以前没有发现的东西? 给定obs 的数量(本例中为 8375 行),如何获得“真正的”完整运行滚动相关性?

【问题讨论】:

    标签: r dplyr correlation zoo rolling-computation


    【解决方案1】:

    函数应该返回一个向量,而不是一个矩阵。使用以下内容(如果您不希望结果被前导 NA 填充,则省略填充参数):

    ccor <- function(x) c(cor(x, method = "spearman"))
    rollapplyr(test, 50, ccor, by.column = FALSE, fill = NA)
    

    还有

    • require 只能在 if (...) 中使用。在您的示例中使用library。这将使调试丢失包的存在变得更容易,因为在这种情况下,它将在library 语句处停止,而不是在以后更难确定原因时停止。

    • 右指的赋值箭头应该是左指的

    • 在 zoo 的开发版本中,FUN= 中指定的函数输出的矩阵或数据框(但不是普通列表)将被分解为向量,因此这将为每个输入行生成一行:

      # install.packages("zoo", repos="http://R-Forge.R-project.org")
      rollapplyr(test, 50, cor, method = "spearman", by.column = FALSE, fill = NA)
      

    【讨论】:

    • 我只是编辑了问题细节没有注意箭头;并感谢require vs library,我从来没有真正深入了解它们之间的区别!现在对我来说太晚了,我稍后会尝试并回复你。谢谢!
    • 它确实像我上面描述的那样工作,虽然不是我想要的;它跨越 25 个向量/列,而不是 5 x 5 矩阵,无法识别实际对,我只能求助于启发式猜测该列代表什么对。不过,这将是一个单独的问题。
    • nr &lt;- nrow(test); nc &lt;- ncol(test); r &lt;- rollapplyr(test, 50, ccor, by.columnn = FALSE, fill = NA); a &lt;- array(t(r), c(nc, nc, nr)); matrix(aperm(a, c(1, 3, 2)),, nc)
    • 坦白说我无语了;您的代码绝对向我展示了基础R 的力量,尤其是apermtidyverse 很高兴拥有,但现在我被敦促深入挖掘 R 本身。非常感谢!
    • 我也试过corrr::correlate;它给了我一个带有嵌套列表的基于列的结果:ccor2 &lt;- function(x) c(correlate(x, method="spearman", diagonal=1, quiet=T)); r2 &lt;- rollapplyr(test, 50, ccor2, by.column=F) 然后我发现这个简短的表达式也给了我一个很好的扁平矩阵:r2 %&gt;% tidyr::as_tibble() %&gt;% tidyr::unnest()corrr::correlate 但是比您向我展示的基本 R 实现至少多花 1 秒。
    猜你喜欢
    • 2023-03-14
    • 2014-01-08
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 2018-03-18
    • 2018-11-17
    相关资源
    最近更新 更多