2012-03-30 9 views
5

Ich möchte Kovarianzmatrizen (und Mittelwertvektoren) mit einem Rollfenster erzeugen. Aber in allen meinen Versuchen stapelt rollapply die Kovarianzmatrizen von cov und läuft aus vor-zugeteiltem Speicherplatz (z. B. wenn meine ursprünglichen Daten 40 Beobachtungen haben, kann rollapply nicht mehr als 40 Zeilen zurückgeben).Kann Rolllapply eine Liste von Matrizen zurückgeben?

Gibt es eine Möglichkeit, dass ich rollapply erhalten kann, um eine Liste von Matrizen zurückzugeben? Oder eine data.frame zurückgeben, die größer ist als die ursprüngliche data.frame, die ich manuell in eine Liste aufteilen kann? Mein Endziel ist es, ein Panel zu nehmen, das Panel in eine Liste von Individuen einzuteilen, die rollenden Kovarianzen und Mittel für jeden Datenrahmen zu berechnen, dann diese Listen von Kovarianzen und Mitteln stromabwärts zu verwenden, um mit einer Menge Individuen zu vergleichen.

Hier ist ein Code. Mein Problem ist, dass my.fun keine Daten von allen Kovarianzmatrix-Kalkulationen zurückgibt. Ist meine beste Option, meine eigene rollapply zu codieren? Oder meine eigene cov, die einen Vektor zurückgibt, den ich zurück in eine Matrix umwandeln? Vielen Dank!

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

Können Sie versuchen, Ihr Ziel klarer zu machen? Kovarianzen zwischen was genau? Es erscheint nicht im Code Und wie viele Gruppen haben Sie sich vorgestellt, dass data.list hat? Daraus entsteht eine Zoo-Serie: 'my.fun (data.list [[1]])'. Hast du das von der sic == 1-Gruppe erwartet? –

+0

@DWin Ich möchte eine Kovarianzmatrix für jedes sic für jedes Jahr basierend auf einem 10-Jahres-Moving-Fenster. Es gibt nichts Heiliges daran, ein "Zoo" -Objekt hier zu haben, ich war gerade schon damit vertraut, wie man ein 'rollapply' verwendet, um einen Skalar zu erzeugen. –

Antwort

2

am rollapply.zoo Code Nach einem Blick, ich glaube nicht, gibt es einen Weg, es zu tun, was Sie wollen. Das Rollen deiner eigenen Funktion ist jedoch nicht so schwierig (Wortspiel beabsichtigt).

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

Das macht es! Vielen Dank! Ich habe auch gemerkt, dass ich 'rollapply' dazu bringen kann, einen Vektor zurückzugeben, und diesen Vektor dann wieder in eine Matrix zurückbiege (ich füge das als Antwort hinzu). –

2

Ich erkannte, dass ich Rollapply Trick in die Rückgabe eines Vektors, dann biegen Sie den Vektor zurück in eine Matrix. Der Trick besteht darin, alply aus dem Paket plyr zu verwenden, um den Vektor zurück in eine Matrix zu biegen.

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) 

Oder für eine Liste von Arrays kann ich alply mit aaply ersetzen. Entfernen

2

die zweite data.list<- und modifizieren my.fun damit gegeben data.df wir folgendes haben (die dem Original ziemlich nahe ist):

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) 

EDIT: Leichte Vereinfachung.

+0

Ehrfürchtig. Vielen Dank! Ich konnte mir nicht vorstellen, wie ich mich "herumreißen" sollte, weil ich immer wieder daran arbeitete, auf der gleichen Liste zu operieren. Das ist nett. –

Verwandte Themen