2013-06-03 13 views
5

Często zajmuję się danymi w formatach xts, a często trzeba je skalować (powiedzmy, aby były równe 100 w niektórych dniach). Obecnie robię to za pomocą funkcji, która działa przy użyciu for-loop - jednak to nie wydaje się być bardzo funkcjonalne.kolumny skali obiektu xts

Oto jak zrobić to teraz:

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

Czy jest jakiś sprytny apply typu funkcja, która jest drogą R to zrobić?

Odpowiedz

4

sweep może służyć do dzielenia macierzy za wiersz.

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

+1, super - dzięki. – ricardo

+0

Nice. Zakładałem, że 'zamiatanie' nie zadziała bez użycia' coredata (dfx [1]) 'ale wewnętrzne wywołanie' tablica' zajmie się tym dla ciebie. –

3

Można użyć apply.daily. Zauważ, że nadal musisz używać coredata w wierszu, który chcesz podzielić, ponieważ operacje xts/zoo zawsze wyrównują indeksy przed wykonaniem operacji.

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

+1, dziękuję. więc jeśli to byłyby dane miesięczne, użyłbym apply.monthly? – ricardo

+0

@ricardo: W twoim przykładzie 'dfx' * było * miesięczne i' apply.daily' działało. Działa, ponieważ indeksem dla 'dfx' jest Date. –

+0

Proszę o wybaczenie - nie wypróbowałem tego, zanim zapytałem. Wnioskuję z tego, że 'apply.daily' zadziała wtedy we wszystkich przypadkach? – ricardo