Use agregado con una función que usa datos de dos columnas (por ejemplo, CoV o prod)

StackOverflow https://stackoverflow.com/questions/3823549

  •  26-09-2019
  •  | 
  •  

Pregunta

Tengo una larga serie de tiempo de datos diarios y 101 columnas. Cada mes me gustaría calcular el cov de cada una de las primeras 100 columnas con la columna 101. Esto generaría una covarianza mensual con la columna 101 para cada una de las 100 columnas basadas en datos diarios. Parece que aggregate hace lo que quiero con funciones que tomen un solo vector, como mean, pero no puedo hacer que funcione con cov (o prod).

Por favor avíseme si un dput de unos pocos meses ayudaría.

> library("zoo")
> data <- read.zoo("100Size-BM.csv", header=TRUE, sep=",", format="%Y%m%d")
> head(data[, c("R1", "R2", "R3", "R100", "Mkt.RF")])
                 R1       R2       R3     R100  Mkt.RF
1963-07-01 -0.00212  0.00398 -0.00472 -0.00362 -0.0066
1963-07-02 -0.00242  0.00678  0.00068 -0.00012  0.0078
1963-07-03  0.00528  0.01078  0.00598  0.00338  0.0063
1963-07-05  0.01738 -0.00932 -0.00072 -0.00012  0.0040
1963-07-08  0.01048 -0.01262 -0.01332 -0.01392 -0.0062
1963-07-09 -0.01052  0.01048  0.01738  0.01388  0.0045

mean Funciona muy bien y me da los datos mensuales que quiero.

> mean.temp <- aggregate(data[, 1:100], as.yearmon, mean)
> head(mean.temp[, 1:3])
                    R1            R2            R3
Jul 1963  0.0003845455  7.545455e-05  0.0004300000
Aug 1963 -0.0006418182  2.412727e-03  0.0022263636
Sep 1963  0.0016250000  1.025000e-03 -0.0002600000
Oct 1963 -0.0007952174  2.226522e-03  0.0004873913
Nov 1963  0.0006555556 -5.211111e-03 -0.0013888889
Dec 1963 -0.0027066667 -1.249524e-03 -0.0005828571

Pero no puedo obtener una función que use dos columnas/vectores diferentes para funcionar.

> cov.temp <- aggregate(data[, 1:100], as.yearmon, cov(x, data[, "Mkt.RF"]))
Error in inherits(x, "data.frame") : object 'x' not found

Ni puedo hacer que funcione haciendo un cov envoltura.

> f <- function(x) cov(x, data[, "Mkt.RF"])
> cov.temp <- aggregate(data[, 1:100], as.yearmon, f)
Error in cov(x, data[, "Mkt.RF"]) : incompatible dimensions

¿Debería hacer esto con un for ¿círculo? Espero que haya más R camino. ¡Gracias!

¿Fue útil?

Solución

Olvidaste el function(x) declaración y debe asegurarse de obtener el subconjunto mensual correcto de data (que pisotea el data función, por cierto). Prueba esto:

> aggregate(data, as.yearmon, function(x) cov(x,data[index(x),"Mkt.RF"]))
                  R1         R2        R3        R100     Mkt.RF
Jul 1963  1.3265e-05 2.0340e-05 3.464e-05  2.2575e-05  6.267e-05
Aug 1963 -7.1295e-05 2.8875e-05 1.000e-06 -9.9700e-06 -2.608e-05

*Tenga en cuenta que cambié las últimas tres observaciones en sus datos de ejemplo al mes de agosto, por lo que habría más de un mes de producción.

Otros consejos

Puedes usar el enfoque que escribí aquí, a saber, hacer algo como:

tapply(1:nrow(data), data$group, function(s) cov(data$x[s], data$y[s]))

En aggregate(), Como es común a muchas funciones R que aplican otras funciones R a los subconjuntos de datos, usted nombra la función que desea aplicar, en este caso agregando FUN = cov para usted aggregate() llamar. Luego puede proporcionar argumentos a esta función como parte del ... argumento especial.

Puedes pasar data[, "Mkt.RF"]) como argumento y de función cov(), así que algo como esto debería funcionar:

cov.temp <- aggregate(data[, 1:100], as.yearmon, FUN = cov, y = data[, "Mkt.RF"])

Sin embargo, en este caso, esto no parece funcionar, ya que necesita manejar la naturaleza del zoológico de los datos y poder subconjunto data[, "Mkt.RF"] De la misma manera la otra data[,1:100]1 columns are broken up byagregado () `. Entonces, una alternativa es especificar una función en línea, como esto:

cov.temp <- aggregate(data[, 1:100], as.yearmon, 
                      FUN = function(x) cov(x, y = data[index(x), "Mkt.RF"]))

Aquí hay un ejemplo que debería quedarse sin el cuadro:

library("zoo")
dat <- data.frame(matrix(rnorm(365*10*6), ncol = 6))
Dates <- seq.Date(from = as.Date("1963-07-01"), by = "days", length = 365*10)
dat2 <- zoo(dat, order.by = Dates)

Que nos da:

> head(dat2)
                    X1         X2         X3          X4         X5         X6
1963-07-01  0.30910867  0.5539864  0.6433690  0.20608146 -1.7706003 -0.4607610
1963-07-02 -0.02519616 -0.1856305  1.0419578  1.01319153  0.8671110  0.1196251
1963-07-03  1.56464024  0.4980238  0.2976338  0.05654036  0.4984225 -1.4626501
1963-07-04 -0.24028698 -1.4365257  0.5707873 -0.05851961 -0.7176343  0.1233137
1963-07-05 -0.87770815 -0.5217949 -2.4875626 -0.08200408 -0.6121038 -0.3881126
1963-07-06 -0.53660576 -1.1098966  2.7411511 -1.37106883 -0.5891641  1.6322411

Ahora, asumamos X6 es tuyo "Mkt.RF" columna y nos agregaremos a través de DAT2 [, 1: 5]:

cov.temp <- aggregate(dat2[, 1:5], as.yearmon, 
                      FUN = function(x) cov(x, y = dat2[index(x),"X6"]))
head(cov.temp)

Cuyos rendimientos:

> head(cov.temp)
                  X1          X2           X3          X4          X5
Jul 1963 -0.30185387  0.09802210  0.019282934 -0.03621272  0.05332324
Aug 1963  0.14739044  0.04276340  0.081847499 -0.35195736 -0.14680017
Sep 1963  0.56698393 -0.08371676  0.003870935 -0.05948173  0.07550769
Oct 1963  0.00711595 -0.07939798  0.118030943 -0.22065278 -0.12474052
Nov 1963  0.06551982  0.22848268  0.231967655  0.02356194 -0.24272566
Dec 1963  0.23866775  0.29464398 -0.034313793  0.09694199 -0.10481527

Hth

Terminé usando aggregate para formatear los datos, pero tomó aproximadamente 50 minutos por cálculo de cov con cada factor. Por capricho probé el plyr Solución, que tiene grandes ganancias.

cov.fn <- function(x) nrow(x) * cov(x[, 1:100], x[, 101])
temp <- zoo(daply(data, .(as.yearmon(index(data))), cov.fn), unique(as.yearmon(index(data))))

Esto toma alrededor de cinco segundos (600x veces más rápido). Supongo que se tienen grandes ganancias de velocidad para mejorar la eficiencia de las operaciones de subsecientes.

Gracias por toda la ayuda. Aprendí mucho sobre este.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top