2012-03-30 6 views
5

Me gustaría generar matrices de covarianza (y vectores promedio) usando una ventana móvil. Pero en todos mis intentos, rollapply apila las matrices de covarianza de cov y se queda sin espacio preasignado (por ejemplo, si mis datos originales tienen 40 observaciones, entonces rollapply no puede devolver más de 40 filas).¿Puede una devolución de rollapply una lista de matrices?

¿Hay alguna manera de que pueda obtener rollapply para devolver una lista de matrices? O para devolver un data.frame que es más grande que el data.frame original, que puedo dividir manualmente en una lista? Mi objetivo final es tomar un panel, dividir el panel en una lista de data.frame s individuales, calcular las covarianzas y los medios para cada marco de datos, luego usar estas listas de covarianzas y medias aguas abajo para compararlas con un grupo de individuos.

Aquí hay algunos códigos. Mi problema es que my.fun no devolverá los datos de todas las calucificaciones de la matriz de covarianza. ¿Es mi mejor opción codificar mi propio rollapply? O mi propio cov que devuelve un vector que vuelvo a convertir en una matriz? ¡Gracias!

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

¿Puedes intentar hacer tu objetivo más claro? Covarianzas entre qué exactamente? No aparece en el código ¿Y cuántos grupos imaginaste que data.list tiene? Esto produce una serie de zoológico: 'my.fun (data.list [[1]])'. ¿Es eso lo que esperabas del grupo sic == 1? –

+0

@DWin Me gustaría una matriz de covarianza para cada sic para cada año en función de una ventana móvil de 10 años. No hay nada sagrado en tener un objeto 'zoo' aquí, ya estaba familiarizado con cómo usar un' rollapply' para generar un escalar. –

Respuesta

2

Después de mirar el código rollapply.zoo, yo no creo que haya una manera de hacer que haga lo que quiera. No obstante, no es tan difícil cambiar tu propia función (juego de palabras).

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

¡Eso lo hace! ¡Gracias! También me di cuenta de que puedo engañar a 'rollapply' para que devuelva un vector, y luego doblo ese vector nuevamente en una matriz (lo agregaré como respuesta). –

2

Me di cuenta de que puedo engañar a rollapply para que devuelva un vector, luego doblo ese vector de nuevo en una matriz. El truco está en usar alply del paquete plyr para doblar el vector de vuelta a una matriz.

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) 

O, para una lista de matrices puedo reemplazar alply con aaply.

2

quitar el segundo data.list<- y modificar my.fun por lo que, dada data.df tenemos los siguientes (que es razonablemente cerca de la original):

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: Leve simplificación.

+0

Impresionante. ¡Gracias! No pude encontrar la manera de "resolver" porque estaba decidido a operar una y otra vez en la misma lista. Esto es bonito. –

Cuestiones relacionadas