2012-05-11 16 views
7

Tengo una serie temporal de eventos (publicaciones) que utilizan xts, y quiero calcular el número de eventos que ocurren en una ventana semanal rodante (o quincenal, o 3 días, etc.). Los datos se ve así:Ventana emergente sobre series temporales irregulares

    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 

que debe producir algo así como

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

para una ventana de 2 días. He investigado rollapply, apply.rolling desde PerformanceAnalytics, etc., y todos ellos asumen datos de series temporales regulares. Traté de cambiar todas las veces hasta el día en que se produjo la publicación y usar algo como ddply para agrupar cada día, lo que me acerca. Sin embargo, un usuario puede no publicar todos los días, por lo que la serie de tiempo seguirá siendo irregular. Podría llenar los espacios con ceros, pero eso podría inflar mucho mis datos y ya es bastante grande.

¿Qué debo hacer?

+2

La solución para esto no existe actualmente en el paquete XTS, pero esta petición se produce lo suficiente que he empezado a pensar en incluir una solución. –

+0

¿Tiene una actualización de @JoshuaUlrich? ¿O algo así como el efecto de la respuesta a continuación que completará los días perdidos con ceros o datos de NA para que podamos usar 'rollapply'? Creo que puedo usar 'merge' ... – flodel

+0

@flodel: esta pregunta no necesita lo que pensé que era (ver mi respuesta). Pensé que querían mirar hacia atrás 'n' días en cada observación de su serie original, que es un problema mucho más difícil de resolver. –

Respuesta

4

Esto parece funcionar:

# 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 

no parece ser demasiado lento (aunque la matriz mat obtendrá dimensiones n * n). Traté de reemplazar n = 30 con n = 3000 (que crea una matriz de 9 millones de elementos = 72 MB) y todavía era razonablemente rápido en mi computadora. Para conjuntos de datos muy grandes, pruebe primero un subconjunto ... También será más rápido usar algunas de las funciones del paquete Matrix (bandSparse) para crear la matriz mat.

+0

Esta es una buena forma de aplicar una ventana rodante a algo, pero si no le das un ejemplo que muestra cómo aplicar esto a una serie de tiempo real (expresar como objetos de fecha y hora POSIXct como en la pregunta original), difícilmente responde la pregunta – plannapus

+0

Con un vector de objetos POSIXct espaciados irregularmente 'data <- sample (seq (as.POSIXct (" 2012/01/01 "), as.POSIXct (" 2012/01/31 "), by =" hours ") , 30) ', puede reemplazar su línea' date.table' por: 'date.table <- table (cut (data," days "))' y luego proceder como lo hizo, y debería funcionar. – plannapus

+0

plannapus, gracias por sus adiciones con respecto a los objetos POSIXct. –

3

Aquí es una solución utilizando 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 
Cuestiones relacionadas