Uso aggregato con una funzione che utilizza i dati di due colonne (ad esempio COV o prod)
Domanda
Ho una serie temporale lunga dei dati giornalieri e 101 colonne. Ogni mese vorrei calcolare la cov
di ciascuna delle prime 100 colonne con la colonna 101 °. Questo genererebbe un covarianza mensile con la colonna 101 ° per ciascuna delle 100 colonne sulla base di dati giornalieri. Sembra che aggregate
fa quello che voglio con funzioni che richiedono un singolo vettore, come mean
, ma non riesco a farlo funzionare con cov
(o prod
).
Per favore fatemi sapere se un dput
di pochi mesi sarebbe di aiuto.
> 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
grandi opere, e mi dà i dati mensili che voglio.
> 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
Ma non posso avere una funzione che utilizza due diverse colonne / vettori di lavoro.
> cov.temp <- aggregate(data[, 1:100], as.yearmon, cov(x, data[, "Mkt.RF"]))
Error in inherits(x, "data.frame") : object 'x' not found
E non posso farlo funzionare facendo un wrapper cov
.
> 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
devo fare questo con un ciclo for
? Sto sperando che ci sia un modo più R
. Grazie!
Soluzione
Si dimenticò la dichiarazione function(x)
ed è necessario essere sicuri di ottenere il corretto sottoinsieme mensile di data
(che calpesta la funzione data
, tra l'altro). Prova questo:
> 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
* Nota che ho cambiato le ultime tre osservazioni nei dati di esempio per il mese di agosto, così non ci sarebbe più di un mese di uscita.
Altri suggerimenti
È possibile utilizzare l'approccio che ho scritto qui , vale a dire fare qualcosa di simile:
tapply(1:nrow(data), data$group, function(s) cov(data$x[s], data$y[s]))
In aggregate()
, come è comune a molte funzioni di ricerca che si applicano altre funzioni R per sottoinsiemi di dati, è il nome della funzione che si desidera applicare, in questo caso con l'aggiunta di FUN = cov
alla chiamata aggregate()
. È quindi possibile fornire argomenti per questa funzione come parte dell'argomento ...
speciale.
È possibile passare data[, "Mkt.RF"])
come argomento della funzione y
cov()
, in modo da qualcosa come questo dovrebbe funzionare:
cov.temp <- aggregate(data[, 1:100], as.yearmon, FUN = cov, y = data[, "Mkt.RF"])
Tuttavia, in questo caso, questo non sembra funzionare come si deve gestire lo zoo-natura dei dati ed essere in grado di sottoinsieme data[, "Mkt.RF"]
allo stesso modo l'altro data[,1:100]1 columns are broken up by
aggregate () `. Quindi, un alternativa è quella di specificare una funzione in linea , in questo modo:
cov.temp <- aggregate(data[, 1:100], as.yearmon,
FUN = function(x) cov(x, y = data[index(x), "Mkt.RF"]))
Ecco un esempio che dovrebbe correre fuori dalla scatola:
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)
Il che ci dà:
> 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
Ora, lascia supporre X6
è la colonna "Mkt.RF"
e ti aggregare oltre DAT2 [, 1: 5]:
cov.temp <- aggregate(dat2[, 1:5], as.yearmon,
FUN = function(x) cov(x, y = dat2[index(x),"X6"]))
head(cov.temp)
Quali rendimenti:
> 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
Ho finito per usare aggregate
per formattare i dati, ma ci sono voluti circa 50 minuti per il calcolo di cov
con ogni fattore. Per un capriccio ho provato la soluzione plyr
, che ha enormi guadagni.
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))))
Questa operazione richiede circa cinque secondi (600x volte più veloce). Credo che ci sono grandi guadagni di velocità per essere avuto nel migliorare l'efficienza delle operazioni sottoinsiemi.
Grazie, tutti, per l'aiuto. Ho imparato molto su questo.