Utilisation globale avec une fonction qui utilise les données de deux colonnes (par exemple cov ou prod)
Question
J'ai une longue série chronologique des données quotidiennes et 101 colonnes. Chaque mois, je souhaite calculer la cov
de chacune des 100 premières colonnes à la colonne 101e. Cela générerait une covariance mensuelle avec la colonne 101e pour chacune des 100 colonnes à partir 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
).
S'il vous plaît laissez-moi savoir si un dput
de quelques mois serait utile.
> 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 de travail différents.
> 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 de 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
dois-je faire cela avec une boucle de for
? J'espère qu'il ya un moyen plus R
. Merci!
La solution
Vous avez oublié la déclaration de function(x)
et vous devez vous assurer d'obtenir 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.
Autres conseils
Dans aggregate()
, comme cela 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 que 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 y
argument 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 regrouper 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
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 (600x fois plus rapide). Je suppose qu'il ya des gains importants de vitesse à avoir dans l'amélioration de l'efficacité des opérations de sous-ensembles.
Merci, tous, pour l'aide. J'ai appris beaucoup sur celui-ci.