2012-03-30 114 views
5

我想用滚动窗口生成协方差矩阵(和平均向量)。但是,在我所有的尝试rollapply中,从cov中叠加了协方差矩阵,并且耗尽了预先分配的空间(例如,如果我的原始数据有40个观察值,那么rollapply不能返回超过40行)。Rollapply可以返回矩阵列表吗?

有没有办法让rollapply返回一个矩阵列表?或者返回大于原始data.framedata.frame,我可以手动将它分割成列表?我的最终目标是建立一个小组,将小组分成一个个人列表data.frame s,计算每个数据框的滚动协方差和平均值,然后使用这些协方差列表和下游平均值与一群个体进行比较。

这是一些代码。我的问题是,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) 
+0

你能试着让你的目标更清楚吗?协调什么到底是什么?它没有出现在代码中您认为data.list有多少组?这会产生一个动物园系列:'my.fun(data.list [[1]])'。这就是你期望从sic == 1组得到的结果吗? – 2012-03-30 17:59:17

+0

@DWin我想每个基于10年移动窗口的每个sic的协方差矩阵。在这里没有什么神圣的关于有'动物园'对象,我只是已经熟悉如何使用'rollapply'来产生标量。 – 2012-03-30 18:43:51

回答

2

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)) 
+0

就是这样!谢谢!我也意识到,我可以欺骗'rollapply'返回一个向量,然后将该向量弯曲回矩阵(我将它添加为一个答案)。 – 2012-03-30 18:47:09

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) 

或者,阵列的列表,我可以代替aaplyalply

2

取下第二data.list<-和修改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) 

编辑:轻微简化。

+0

太棒了。谢谢!我无法弄清楚如何避开'alply',因为我固定在同一张名单上反复操作。这很好。 – 2012-03-30 19:32:10