【问题标题】:Can rollapply return a list of matrices?rollapply 可以返回矩阵列表吗?
【发布时间】:2012-04-14 09:27:23
【问题描述】:

我想使用滚动窗口生成协方差矩阵(和均值向量)。但在我所有的尝试中,rollapply 将来自cov 的协方差矩阵堆叠起来并用完预分配的空间(例如,如果我的原始数据有 40 个观察值,那么rollapply 不能返回超过 40 行)。

有没有办法让rollapply 返回矩阵列表?或者返回大于原始data.framedata.frame,我可以手动将其拆分为列表?我的最终目标是制作一个面板,将面板拆分为一个单独的data.frames 列表,计算每个数据框的滚动协方差和均值,然后使用这些协方差列表和均值下游与一群人进行比较。

这是一些代码。我的问题是my.fun 不会从所有协方差矩阵计算中返回数据。编写自己的rollapply 是我最好的选择吗?还是我自己的cov 返回一个我转换回矩阵的向量?谢谢!

library("zoo")
data.df <- data.frame(sic = rep(1:10, each = 40),
                      year = rep(1:40, len = 10*40),
                      one = rnorm(10*40),
                      two = 2*rnorm(10*40),
                      three = 3*rnorm(10*40))
data.list <- split(data.df, data.df$sic)
data.list <- lapply(data.list, zoo)
my.fun <- function(x) {
    x <- x[, c("one", "two", "three")]
    rollapply(x,
              width = 10, 
              FUN = cov,
              by.column = F, 
              align = "right")
}
cov.list <- lapply(data.list, FUN = my.fun)

【问题讨论】:

  • 你能试着让你的目标更明确吗?之间的协方差究竟是什么?它没有出现在代码中您认为 data.list 有多少组?这会产生一个动物园系列:my.fun(data.list[[1]])。这是您对 sic==1 小组的期望吗?
  • @DWin 我想要一个基于 10 年移动窗口的每年每个 sic 的协方差矩阵。在这里拥有zoo 对象并没有什么神圣之处,我只是已经熟悉如何使用rollapply 来生成标量。

标签: r zoo


【解决方案1】:

看了rollapply.zoo 代码后,我认为没有办法让它做你想做的事。不过,滚动自己的函数并不难(双关语)。

rollcov <- function(x, width=10) {
  len <- NROW(x)
  add <- rep(1:(len-width)-1,each=width)
  seq.list <- split(rep(1:width,len-width)+add, add)
  lapply(seq.list, function(y) cov(x[y,]))
}

rollcov(data.list[[1]][,c("one","two","three")],10)
all <- lapply(data.list, function(x) rollcov(x[,c("one","two","three")],10))

【讨论】:

  • 就是这样!谢谢!我还意识到我可以欺骗rollapply 返回一个向量,然后将该向量弯曲回一个矩阵(我会将其添加为答案)。
【解决方案2】:

我意识到我可以欺骗 rollapply 返回一个向量,然后将该向量弯曲回一个矩阵。诀窍是使用plyr 包中的alply 将向量弯曲回矩阵。

library("plyr")
library("zoo")
data.df <- data.frame(sic = rep(1:10, each = 40),
                      year = rep(1:40, len = 10*40),
                      one = rnorm(10*40),
                      two = 2*rnorm(10*40),
                      three = 3*rnorm(10*40))
data.list <- split(data.df, data$sic)
data.list <- lapply(data.list, zoo)
my.fun <- function(x) {
    x <- x[, c("one", "two", "three")]
    rollapply(x,
              width = 10, 
              function(x) as.vector(cov(x)),
              by.column = F, 
              align = "right")
}
my.fun.2 <- function(x) {
    alply(x, 1, matrix, nrow = sqrt(ncol(x)))
}
cov.list <- lapply(data.list, FUN = my.fun)
cov.list.2 <- lapply(cov.list, my.fun.2)

或者,对于数组列表,我可以将 alply 替换为 aaply

【讨论】:

    【解决方案3】:

    删除第二个data.list&lt;- 并修改my.fun 以便给定data.df 我们有以下内容(与原始内容相当接近):

    data.list <- split(data.df, data.df$sic)
    my.fun <- function(x) {
        z <- zoo(x[, c("one", "two", "three")], x$year)
        ccov <- function(x) c(cov(x))
        r <- rollapplyr(z, width = 10, FUN = ccov, by.column = FALSE)
        toMat <- function(tt) matrix(r[tt], ncol(z))
        sapply(paste(time(r)), toMat, simplify = FALSE) # sapply(char,...) adds names
    }
    cov.list <- lapply(data.list, FUN = my.fun)
    

    编辑:稍微简化。

    【讨论】:

    • 太棒了。谢谢!我不知道如何绕过alply,因为我固定在同一个列表上一遍又一遍地操作。这很好。
    猜你喜欢
    • 1970-01-01
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多