2016-07-28 42 views
11

我想計算一組數據(我的x變量的每列)和R中的另一個(y變量)之間的滾動協方差。我想我可以使用其中一個應用功能,但無法找到如何同時滾動兩組輸入。這是我試過的:如何更有效地計算滾動協方差

set.seed(1) 
x<-matrix(rnorm(500),nrow=100,ncol=5) 
y<-rnorm(100) 
rollapply(x,width=5,FUN= function(x) {cov(x,y)}) 
z<-cbind(x,y) 
rollapply(z,width=5, FUN=function(x){cov(z,z[,6])}) 

但是沒有人做我想做的事。一個解決方案,我發現是使用循環,但想知道如果我在R中可以比更高效:

dResult<-matrix(nrow=96,ncol=5) 
for(iLine in 1:96){ 
    for(iCol in 1:5){ 
     dResult[iLine,iCol]=cov(x[iLine:(iLine+4),iCol],y[iLine:(iLine+4)]) 
    } 
} 

這給了我預期的結果:

head(dResult) 


      [,1]  [,2]  [,3]  [,4]  [,5] 
[1,] 0.32056460 0.05281386 -1.13283586 -0.01741274 -0.01464430 
[2,] -0.03246014 0.78631603 -0.34309778 0.29919297 -0.22243572 
[3,] -0.16239479 0.56372428 -0.27476604 0.39007645 0.05461355 
[4,] -0.56764687 0.09847672 0.11204244 0.78044096 -0.01980684 
[5,] -0.43081539 0.01904417 0.01282632 0.35550327 0.31062580 
[6,] -0.28890607 0.03967327 0.58307743 0.15055881 0.60704533 
+1

在徹底的第一篇文章上幹得不錯。 –

回答

8
set.seed(1) 
x<-as.data.frame(matrix(rnorm(500),nrow=100,ncol=5)) 
y<-rnorm(100) 

library(zoo) 

covResult = sapply(x,function(alpha) { 

cov_value = rollapply(cbind(alpha,y),width=5,FUN = function(beta) cov(beta[,1],beta[,2]),by.column=FALSE,align="right") 

return(cov_value) 

}) 

head(covResult) 
#    V1   V2   V3   V4   V5 
#[1,] 0.32056460 0.05281386 -1.13283586 -0.01741274 -0.01464430 
#[2,] -0.03246014 0.78631603 -0.34309778 0.29919297 -0.22243572 
#[3,] -0.16239479 0.56372428 -0.27476604 0.39007645 0.05461355 
#[4,] -0.56764687 0.09847672 0.11204244 0.78044096 -0.01980684 
#[5,] -0.43081539 0.01904417 0.01282632 0.35550327 0.31062580 
#[6,] -0.28890607 0.03967327 0.58307743 0.15055881 0.60704533 

還檢查了:

library(PerformanceAnalytics) 
?chart.rollingCorrelation 
+0

這正是我想要做的在我第二次嘗試_z_變量時,但是我的_apply_函數的命令仍然有限。非常感謝 ! – Djiggy

+0

如果我對@Stibu的評論是正確的,我想這個應該也比我做的_for_循環更快 – Djiggy

1

現在我m運行一些很長的模擬,所以不能使用R,但認爲這應該工作。列的外部應用將列,將其傳遞給rollapply,它將用於與y進行滾動窗口協方差。希望:d

apply(x,2,function(x) rollapply(x,width=5,function(z) cov(x,y))) 
+0

這不起作用。你總是在'rollaply()'內計算完整向量x和y的協方差。因此,每列包含相同的值,重複96次。 – Stibu

6

這與rollapply()sapply()的溶液:

sapply(1:5, function(j) rollapply(1:100, 5, function(i) cov(x[i, j], y[i]))) 

我認爲這是比用for循環,但我檢查溶液更具有可讀性和更R-ISH microbenchmark它似乎比較慢。

+0

哦,我看到我的錯誤(我的R仍然很忙)做得很好! +1 –

+0

確實很有效,謝謝。我想我們沒有時間,因爲你在這裏創建了兩個循環的索引,並不是真的直接對_x和_數據應用_cov_函數,就像你可能用_mapply_ – Djiggy

0

如果你需要的東西更快,你不需要任何的非默認參數cov,您可以使用TTR::runCov。請注意,它默認填充領先的NA

速度差異對大數據更重要。這裏有一個如何使用它的一個例子:

cov_joshua <- function() { 
    apply(x, 2, function(x, y) TTR::runCov(x, y, 5), y = y) 
} 

下面是使用小數據集的OP提供給目前接受的答案進行比較:

cov_osssan <- function() { 
    f <- function(b) cov(b[,1], b[,2]) 
    apply(x, 2, function(a) { 
    rollapplyr(cbind(a,y), width=5, FUN = f, by.column=FALSE) 
    }) 
} 
require(zoo) # for cov_osssan 
require(microbenchmark) 
set.seed(1) 
nr <- 100 
nc <- 5 
x <- matrix(rnorm(nc*nr),nrow=nr,ncol=nc) 
y <- rnorm(nr) 
microbenchmark(cov_osssan(), cov_joshua()) 
# Unit: milliseconds 
#   expr  min  lq median  uq  max neval 
# cov_osssan() 22.881253 24.569906 25.625623 27.44348 32.81344 100 
# cov_joshua() 5.841422 6.170189 6.706466 7.47609 31.24717 100 
all.equal(cov_osssan(), cov_joshua()[-(1:4),]) # rm leading NA 
# [1] TRUE 

現在,使用更大的數據集:

system.time(cov_joshua()) 
# user system elapsed 
# 2.117 0.032 2.158 
system.time(cov_osssan()) 
# ^C 
# Timing stopped at: 144.957 0.36 145.491 

我厭倦了等待(約2.5分鐘後)cov_osssan完成。