2010-09-29 2 views
4

J'ai une longue série chronologique de données quotidiennes et 101 colonnes. Chaque mois, je voudrais calculer le cov de chacune des 100 premières colonnes avec la 101e colonne. Cela générerait une covariance mensuelle avec la 101ème colonne pour chacune des 100 colonnes en fonction des données quotidiennes. Il semble que aggregate fait ce que je veux avec des fonctions qui prennent un seul vecteur, comme mean, mais je ne peux pas le faire fonctionner avec cov (ou prod).Utilisez l'agrégat avec une fonction qui utilise des données provenant de deux colonnes (par exemple cov ou prod)

S'il vous plaît laissez-moi savoir si un dput de quelques mois aiderait.

> 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 fonctionne très bien, et me donne les données mensuelles que je veux.

> 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 

Mais je ne peux pas obtenir une fonction qui utilise deux colonnes/vecteurs différents pour fonctionner.

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

Je ne peux pas le faire faire du travail une enveloppe 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 

Devrais-je le faire avec une boucle for? J'espère qu'il y a une manière plus R. Merci!

+0

Avez-vous regardé ddply à partir du paquet plyr? Je pense que la distribution de l'ensemble de remodelage pourrait bien fonctionner pour cela aussi. J'aurais besoin de quelques lignes de vos données pour l'essayer! –

Répondre

2

Vous avez oublié la déclaration function(x) et vous devez vous assurer que vous obtenez le sous-ensemble mensuel correct de data (qui piétine la fonction data, par la voie). Essayez ceci:

> 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 

* Notez que j'ai changé les trois dernières observations dans votre exemple des données au mois d'Août, donc il y aurait plus d'un mois de la production.

+0

Merci! Je manque toujours une certaine subtilité dans la syntaxe. –

4

Vous pouvez utiliser l'approche que j'ai écrit here, à savoir faire quelque chose comme:

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

Je suis sûr que je peux l'utiliser ailleurs. Merci! Mais j'aime vraiment l'agrégation 'as.yearmon'. –

+1

C'est la seule solution à ce jour qui donne la bonne réponse. Le problème avec les autres est qu'ils semblent supposer qu'un objet zoo est passé à la fonction dans le troisième argument de aggregate.zoo mais ce n'est pas le cas. –

+0

Juste pour clarifier je voulais dire l'approche discutée ici, pas nécessairement le code littéral car le code semble destiné à montrer la direction de la bonne approche plus que le code littéral dont vous avez besoin. Si vous voulez du code pour ce problème, essayez ce qui suit qui utilise la fonction R "by" ordinaire et à la fin retourne l'objet dans un objet zoo: zoo (do.call (rbind, by (data, as.yearmon (temps (données)), fonction (x) cov (x [, 5], x))), unique (as.yearmon (time (data)))) –

2

En aggregate(), comme il est commun à de nombreuses fonctions de R qui appliquent une autre des fonctions de R à des sous-ensembles de données, vous nommez la fonction vous souhaitez appliquer, dans ce cas en ajoutant FUN = cov à votre appel aggregate(). Vous pouvez ensuite fournir des arguments à cette fonction dans le cadre de l'argument spécial ....

Vous pouvez passer data[, "Mkt.RF"]) comme argument y de la fonction cov(), donc quelque chose comme cela devrait fonctionner:

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

Cependant, dans ce cas, cela ne semble pas fonctionner comme vous avez besoin pour gérer le zoo -nature des données et être en mesure de sous-ensemble data[, "Mkt.RF"] de la même manière l'autre data[,1:100]1 columns are broken up by aggregate() `.Ainsi, une alternative est de spécifier une fonction en ligne, comme ceci:

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

Voici un exemple qui devrait fonctionner hors de la boîte:

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) 

Ce qui nous donne:

> 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 

maintenant, laisse supposer X6 est votre colonne "Mkt.RF" et nous allons agréger sur DAT2 [1: 5]:

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

Ce qui donne:

> 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

+0

explication très complète –

0

Je fini par utiliser aggregate pour formater les données, mais il a fallu environ 50 minutes par calcul de cov à chaque facteur. Sur un coup de tête j'ai essayé la solution plyr, qui a des gains énormes.

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)))) 

Cela prend environ cinq secondes (600 fois plus rapide). Je suppose qu'il y a des gains de vitesse importants à améliorer l'efficacité des opérations de sous-ensembles.

Merci à tous pour votre aide. J'ai beaucoup appris sur celui-ci.

Questions connexes