2013-06-03 5 views
5

Ich habe oft mit Daten in xts Formate, und häufig müssen sie skalieren (sagen, an einem Datum gleich 100 sein). Ich mache dies derzeit mit einer Funktion, die mit einem for-loop funktioniert - aber das scheint nicht sehr funktional.skalieren Spalten eines XTS-Objekts

Hier ist, wie ich es jetzt tun:

df1 <- data.frame(rnorm(100), runif(100), 1:100*rnorm(100)) 
dfx <- xts(df1, order.by = seq(as.Date("2001-01-01"), by='mon', length.out=100)) 

dfxColScl <- function(dfrm, pos=1, idx = 100) 
{ 
    scaledDF <- dfrm 
    for (i in 1:ncol(dfrm)) { 
     scaledDF[, i] <- dfrm[,i]/as.numeric(dfrm[pos, i]) * idx 
    } 
    return(scaledDF) 
} 

Gibt es eine clevere apply Typ-Funktion, die der R Weg, dies zu tun ist?

Antwort

4

sweep kann verwendet werden, um eine Matrix durch eine Zeile zu teilen.

dfx.scaled2 <- sweep(100*dfx, 2, dfx[1], "/") 
all.equal(dfx.scaled, dfx.scaled2) # same result as @Joshua 
#[1] TRUE 
+0

+1, cool - danke. – ricardo

+0

Schön. Ich nahm an, 'sweep' würde nicht funktionieren, ohne' coredata (dfx [1]) 'zu verwenden, aber der interne Aufruf von' array' kümmert sich darum. –

3

Sie könnten apply.daily verwenden. Beachten Sie, dass Sie immer noch coredata für die Zeile verwenden müssen, nach der Sie teilen möchten, da xts/zoo-Operationen immer nach Index ausgerichtet werden, bevor Sie die Operation ausführen.

dfx.scaled <- apply.daily(dfx, function(x) x/coredata(dfx[1,])*100) 
+0

+1, danke. Wenn das also monatliche Daten wären, würde ich apply.monthly verwenden? – ricardo

+0

@ricardo: In Ihrem Beispiel war 'dfx' * * monatlich und' apply.daily' hat funktioniert. Es funktioniert, weil der Index für "dfx" das Datum ist. –

+0

ich bitte um Verzeihung - ich habe es nicht versucht, bevor ich fragte. Daraus schließe ich, dass "apply.daily" dann in allen Fällen funktioniert? – ricardo