2012-05-11 15 views
7

Ho una serie temporale irregolare di eventi (post) utilizzando xts e voglio calcolare il numero di eventi che si verificano su una finestra settimanale a rotazione (o bisettimanale o 3 giorni, ecc.). I dati si presenta così:Finestra di scorrimento su serie temporali irregolari

    postid 
2010-08-04 22:28:07 867 
2010-08-04 23:31:12 891 
2010-08-04 23:58:05 901 
2010-08-05 08:35:50 991 
2010-08-05 13:28:02 1085 
2010-08-05 14:14:47 1114 
2010-08-05 14:21:46 1117 
2010-08-05 15:46:24 1151 
2010-08-05 16:25:29 1174 
2010-08-05 23:19:29 1268 
2010-08-06 12:15:42 1384 
2010-08-06 15:22:06 1403 
2010-08-07 10:25:49 1550 
2010-08-07 18:58:16 1596 
2010-08-07 21:15:44 1608 

che dovrebbe produrre qualcosa come

    nposts 
2010-08-05 00:00:00  10 
2010-08-06 00:00:00  9 
2010-08-07 00:00:00  5 

per una finestra di 2 giorni. Ho esaminato rollapply, apply.rolling da PerformanceAnalytics, ecc. E tutti presuppongono dati di serie temporali regolari. Ho provato a cambiare tutte le volte per il giorno in cui è stato pubblicato il post e utilizzare qualcosa come ddply per raggruppare ogni giorno, cosa che mi avvicina. Tuttavia, un utente potrebbe non pubblicare tutti i giorni, quindi le serie temporali saranno ancora irregolari. Potrei riempire gli spazi vuoti con lo 0, ma questo potrebbe gonfiare molto i miei dati ed è già abbastanza grande.

Cosa devo fare?

+2

La soluzione per questo attualmente non esiste nel pacchetto XTS, ma questa richiesta viene su abbastanza che ho iniziato a pensare compresa una soluzione. –

+0

Hai un aggiornamento @JoshuaUlrich? O qualcosa dell'effetto della risposta qui sotto che riempirà i giorni mancanti con zero o dati di NAs quindi possiamo usare 'rollapply'? Immagino di poter usare 'unire '... – flodel

+0

@flodel: questa domanda non richiede quello che pensavo facesse (vedi la mia risposta). Ho pensato che volevano guardare indietro 'n' giorni ad ogni osservazione nella loro serie originale, che è un problema molto più difficile da risolvere. –

risposta

4

Questo sembra funzionare:

# n = number of days 
n <- 30 
# w = window width. In this example, w = 7 days 
w <- 7 

# I will simulate some data to illustrate the procedure 
data <- rep(1:n, rpois(n, 2)) 

# Tabulate the number of occurences per day: 
# (use factor() to be sure to have the days with zero observations included) 
date.table <- table(factor(data, levels=1:n)) 

mat <- diag(n) 
for (i in 2:w){ 
    dim <- n+i-1 
    mat <- mat + diag(dim)[-((n+1):dim),-(1:(i-1))] 
    } 

# And the answer is.... 
roll.mean.7days <- date.table %*% mat 

sembra non essere troppo lento (anche se la matrice mat otterrà dimensioni n * n). Ho provato a sostituire n = 30 con n = 3000 (che crea una matrice di 9 milioni di elementi = 72 MB) ed era ancora abbastanza veloce sul mio computer. Per set di dati molto grandi, provare prima su un sottoinsieme ... Sarà anche più veloce usare alcune delle funzioni nel pacchetto Matrix (bandSparse) per creare la matrice mat.

+0

Questo è un buon modo per applicare una finestra mobile a qualcosa, ma se non si fornisce un esempio che mostra come applicarlo a una serie temporale effettiva (espressa come POSIXct oggetti data-ora come nella domanda originale), difficilmente risponde alla domanda. – plannapus

+0

Con vettori di oggetti POSIXct con spaziatura irregolare 'dati <- campione (seq (come.POSIXct (" 2012/01/01 "), as.POSIXct (" 2012/01/31 "), da =" ore ") , 30) ', puoi sostituire la tua riga' date.table' di: 'date.table <- table (cut (data," days "))' e poi procedi come hai fatto, e dovrebbe fare il trucco. – plannapus

+0

plannapus, grazie per le aggiunte relative agli oggetti POSIXct. –

3

Ecco una soluzione che utilizza XTS:

x <- structure(c(867L, 891L, 901L, 991L, 1085L, 1114L, 1117L, 1151L, 
    1174L, 1268L, 1384L, 1403L, 1550L, 1596L, 1608L), .Dim = c(15L, 1L), 
    index = structure(c(1280960887, 1280964672, 1280966285, 
    1280997350, 1281014882, 1281017687, 1281018106, 1281023184, 1281025529, 
    1281050369, 1281096942, 1281108126, 1281176749, 1281207496, 1281215744), 
    tzone = "", tclass = c("POSIXct", "POSIXt")), class = c("xts", "zoo"), 
    .indexCLASS = c("POSIXct", "POSIXt"), tclass = c("POSIXct", "POSIXt"), 
    .indexTZ = "", tzone = "") 
# first count the number of observations each day 
xd <- apply.daily(x, length) 
# now sum the counts over a 2-day rolling window 
x2d <- rollapply(xd, 2, sum) 
# align times at the end of the period (if you want) 
y <- align.time(x2d, n=60*60*24) # n is in seconds 
Problemi correlati