2012-03-30 79 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