Alise una serie de tiempo circular / periódica

9

Tengo datos de accidentes automovilísticos por hora del día. Como era de esperar, son altas en la mitad del día y alcanzan su punto máximo en la hora pico. geom_density predeterminado de ggplot2 lo suaviza muy bien

Un subconjunto de los datos, para los accidentes relacionados con la bebida, es alto al final del día (noches y madrugadas) y más alto en los extremos. Pero la geom_density predeterminada de ggplot2 todavía se hunde en el extremo derecho.

¿Qué hacer al respecto? El objetivo es simplemente la visualización: no es necesario (¿existe?) Un análisis estadístico sólido.

Imgur

x <- structure(list(hour = c(14, 1, 1, 9, 2, 11, 20, 5, 22, 13, 21, 
                        2, 22, 10, 18, 0, 2, 1, 2, 15, 20, 23, 17, 3, 3, 16, 19, 23, 
                        3, 4, 4, 22, 2, 21, 20, 1, 19, 18, 17, 23, 23, 3, 11, 4, 23, 
                        4, 7, 2, 3, 19, 2, 18, 3, 17, 1, 9, 19, 23, 9, 6, 2, 1, 23, 21, 
                        22, 22, 22, 20, 1, 21, 6, 2, 22, 23, 19, 17, 19, 3, 22, 21, 4, 
                        10, 17, 23, 3, 7, 19, 16, 2, 23, 4, 5, 1, 20, 7, 21, 19, 2, 21)
               , count = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L))
          , .Names = c("hour", "count")
          , row.names = c(8L, 9L, 10L, 29L, 33L, 48L, 51L, 55L, 69L, 72L, 97L, 108L, 113L, 
                          118L, 126L, 140L, 150L, 171L, 177L, 184L, 202L, 230L, 236L, 240L, 
                          242L, 261L, 262L, 280L, 284L, 286L, 287L, 301L, 318L, 322L, 372L, 
                          380L, 385L, 432L, 448L, 462L, 463L, 495L, 539L, 557L, 563L, 566L, 
                          570L, 577L, 599L, 605L, 609L, 615L, 617L, 624L, 663L, 673L, 679L, 
                          682L, 707L, 730L, 733L, 746L, 754L, 757L, 762L, 781L, 793L, 815L, 
                          817L, 823L, 826L, 856L, 864L, 869L, 877L, 895L, 899L, 918L, 929L, 
                          937L, 962L, 963L, 978L, 980L, 981L, 995L, 1004L, 1005L, 1007L, 
                          1008L, 1012L, 1015L, 1020L, 1027L, 1055L, 1060L, 1078L, 1079L, 
                          1084L)
          , class = "data.frame")

ggplot(x, aes(hour)) + 
  geom_bar(binwidth = 1, position = "dodge", fill = "grey") +
  geom_density() + 
  aes(y = ..count..) +
  scale_x_continuous(breaks = seq(0,24,4))

Feliz para cualquiera con un mejor vocabulario de estadísticas para editar esta pregunta, especialmente el título y las etiquetas.

nacnudus
fuente

Respuestas:

6

Para hacer un suavizado periódico (en cualquier plataforma), solo agregue los datos a sí mismos, suavice la lista más larga y corte los extremos.

Aquí hay una Rilustración:

y <- sqrt(table(factor(x[,"hour"], levels=0:23)))
y <- c(y,y,y)
x.mid <- 1:24; offset <- 24
plot(x.mid-1, y[x.mid+offset]^2, pch=19, xlab="Hour", ylab="Count")
y.smooth <- lowess(y, f=1/8)
lines(x.mid-1, y.smooth$y[x.mid+offset]^2, lwd=2, col="Blue")

(Debido a que estos son los recuentos he elegido para suavizar sus raíces cuadradas; estaban de nuevo convertido a los recuentos para el trazado.) El lapso en lowessque ha sido reducido considerablemente de su valor predeterminado de f=2/3porque (a) ahora estamos procesando una matriz tres veces más largo, que debe hacer que reduzcamos a , y (b) quiero una suavidad bastante local para que no aparezcan efectos de punto final apreciables en el tercio medio.F2/ /9 9

Ha hecho un buen trabajo con estos datos. En particular, la anomalía en la hora 0 se ha suavizado hasta el final.

Trama

whuber
fuente
Esto responde a mi necesidad de una visualización simple, pero fuera de interés, ¿es un poco un error? ¿Usar algo del enlace de Nick evitaría los efectos de punto final?
nacnudus
1
Esto es exactamente equivalente al método que utilicé siempre que el ancho de la ventana se elija con cuidado, como lo hizo @whuber. Pero el software R está disponible para hacer lo que hice. (Originalmente estaba delegando la tarea de encontrarlo a los expertos de R, pero no se dieron cuenta.)
Nick Cox
3
No lo veo como un problema: esta técnica se basa en la definición de periodicidad. Funciona para cualquier local sin problemas. (No funcionará para un global suave, pero eso no es un problema, porque la mayoría de los suavizadores globales se derivan de métodos inherentemente periódicos como la serie Fourier de todos modos.) @Nick One no tiene que tener mucho cuidado: cuando se utiliza un suavizador local de máximo medio ancho , solo se necesita agregar los últimos valores de la secuencia al principio y el primer al final, pero no hay daño en expandir conservativamente la secuencia por más: es menos eficiente . kk-1k-1
whuber
1
@whuber Muy cierto. Estaba aludiendo a la verdad de que lo que agregas como copias delante y detrás de los datos reales debe ser coherente con cuánto suavizas.
Nick Cox
7

No uso R rutinariamente y nunca lo he usado ggplot, pero aquí hay una historia simple, o eso supongo.

La hora del día es manifiestamente una variable circular o periódica. En sus datos tiene horas 0 (1) 23 que se ajustan, de modo que 23 es seguido por 0. Sin embargo, ggplotno lo sabe, al menos por la información que le ha proporcionado. En lo que a él respecta, podría haber valores en -1, -2, etc. o en 24, 25, etc. y, por lo tanto, parte de la probabilidad se suaviza más allá de los límites de los datos observados, y de hecho más allá de los límites de Los posibles datos.

Esto también ocurrirá con sus datos principales, pero no es tan notable.

Si desea estimar la densidad del núcleo para dichos datos, necesita una rutina lo suficientemente inteligente como para manejar adecuadamente tales variables periódicas o circulares. "Correctamente" significa que la rutina se suaviza en un espacio circular, reconociendo que 0 sigue a 23. De alguna manera, el suavizado de tales distribuciones es más fácil que el caso habitual, ya que no hay problemas de límites (ya que no hay límites). Otros deberían poder aconsejar sobre las funciones a utilizar en R.

Este tipo de datos se ubica en algún lugar entre series temporales periódicas y estadísticas circulares.

Los datos presentados tienen 99 observaciones. Para eso, un histograma funciona bastante bien, aunque puedo ver que es posible que desee suavizarlo un poco.

ingrese la descripción de la imagen aquí

(ACTUALIZACIÓN) Es una cuestión de gusto y juicio, pero consideraría su curva suave drásticamente exagerada.

Aquí, como muestra, hay una estimación de la densidad de dos pesos. Utilicé mi propio programa Stata para datos circulares en grados con la conversión ad hoc 15 * (hora + 0.5) pero densidades expresadas por hora. Esto, por el contrario, está un poco sublimado, pero puede ajustar sus elecciones.

ingrese la descripción de la imagen aquí

Nick Cox
fuente
1
Estoy de acuerdo en que está demasiado suavizado, pero es el principio al que me refiero. Buscar en Google su útil vocabulario (circular, periódico) descubre sorprendentemente poco interés en este tipo de problema, pero esperaré un poco más a que alguien intervenga con el consejo de R.
nacnudus
5

Al hacer el 4253H de Tukey, dos veces en tres copias concatenadas los recuentos brutos y luego tomar el conjunto medio de valores suavizados da la misma imagen que la debilidad de Whuber en las raíces cuadradas de los recuentos.
ingrese la descripción de la imagen aquí

Ray Koopman
fuente
2
+1 Prefiero los suavizadores de Tukey y me alegra ver un ejemplo de uno aquí.
Whuber
1
Esta receta precisa fue ideada por Paul F. Velleman, pero sin duda bajo la guía de Tukey. El "42" reduce los artefactos de escalones.
Nick Cox
2

Además, y como una alternativa más compleja, a lo que se ha sugerido, es posible que desee buscar splines periódicos. Puede encontrar herramientas para ajustarlos en los paquetes R splinesy mgcv. La ventaja que veo sobre los enfoques ya sugeridos es que puede calcular los grados de libertad del ajuste, que no son obvios con el método de 'tres copias'.

F. Tusell
fuente
1
(+1) Algunos comentarios: Primero, "tres copias" es una aplicación particular, no una regla general. En segundo lugar, creo que el cálculo de DF es igual de simple: la cantidad de datos sigue siendo la misma y se resta el número de parámetros utilizados para ajustar la spline.
whuber
@whuber: simplemente no está claro para mí cómo hacer el último bit (cómo calcular los parámetros utilizados para ajustar la spline si la ajusta a las "tres copias").
F. Tusell
1
La parte de copia no cambia la cantidad de datos, por lo que todo lo que importa al estimar el DF es contar los parámetros utilizados por las splines.
whuber
1

Otro enfoque más, splines periódicos (como se sugiere en la respuesta de F.Tusell), pero aquí mostramos también una implementación en R. Usaremos una película de Poisson para ajustarse a los recuentos de histograma, resultando en el siguiente histograma con suavizado:

ingrese la descripción de la imagen aquí

El código utilizado (comenzando con el objeto de datos xdado en cuestión):

library(pbs) # basis for periodic spline

x.tab <- with(x, table(factor(hour,levels=as.character(0:23))))
x.df <- data.frame(time=0:23, count=as.vector(x.tab))
mod.hist <- with(x.df, glm(count ~ pbs::pbs(time, df=4, Boundary.knots=c(0,24)), family=poisson))
pred <- predict(mod.hist, type="response", newdata=data.frame(time=0:24))

with(x.df, {plot(time, count,type="h",col="blue", main="Histogram") ; lines(time, pred[1:24], col="red")} )
kjetil b halvorsen
fuente