2012-03-30 8 views
5

Vorrei generare matrici di covarianza (e media) utilizzando una finestra a rotazione. Ma in tutti i miei tentativi, rollapply impila le matrici di covarianza da cov e esaurisce lo spazio pre-allocato (ad es., Se i miei dati originali hanno 40 osservazioni, allora rollapply non può restituire più di 40 righe).È possibile rollopply restituire un elenco di matrici?

C'è un modo per ottenere rollapply per restituire un elenco di matrici? O per restituire un data.frame che è più grande dell'originale data.frame, che posso dividere manualmente in un elenco? Il mio obiettivo finale è quello di prendere un pannello, dividere il pannello in un elenco di singoli data.frame s, calcolare le covarianze e i mezzi a rotazione per ciascun frame di dati, quindi utilizzare questi elenchi di covarianze e mezzi a valle per confrontarli con un gruppo di individui.

Ecco un codice. Il mio problema è che my.fun non restituirà i dati da tutti i calibri di matrice di covarianza. È la mia migliore opzione per codificare il mio rollapply? O il mio cov che restituisce un vettore convertito in una matrice? Grazie!

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

Puoi provare a rendere più chiaro il tuo obiettivo? Covarianze tra cosa esattamente? Non appare nel codice E quanti gruppi hai immaginato che data.list abbia? Questo produce una serie di zoo: 'my.fun (data.list [[1]])'. È quello che ti aspettavi dal gruppo sic == 1? –

+0

@DWin Vorrei una matrice di covarianza per ogni sic per ogni anno in base a una finestra mobile di 10 anni. Non c'è nulla di sacro nell'avere un oggetto 'zoo' qui, avevo già familiarità con l'uso di un' rollapply' per generare uno scalare. –

risposta

2

Dopo guardando il codice rollapply.zoo, non credo che ci sia un modo per fargli fare quello che vuoi. Rullare la propria funzione non è poi così difficile (gioco di parole).

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

Questo lo fa! Grazie! Ho anche capito che posso ingannare 'rollapply' nel restituire un vettore, quindi piegare quel vettore in una matrice (lo aggiungerò come risposta). –

2

Mi sono reso conto che posso ingannare rollapply nel restituire un vettore, quindi piegare quel vettore in una matrice. Il trucco sta usando alply dal pacchetto plyr per piegare il vettore in una matrice.

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) 

Oppure, per un elenco di array posso sostituire alply con aaply.

2

Rimuovere la seconda data.list<- e modificare my.fun affinché proposta data.df abbiamo la seguente (che è ragionevolmente vicino all'originale):

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: Leggera semplificazione.

+0

Fantastico. Grazie! Non riuscivo a capire come aggirare 'alply' perché ero fisso a funzionare più e più volte nella stessa lista. Questo è carino. –

Problemi correlati