Detección de cambios en series de tiempo (ejemplo R)

18

Me gustaría detectar cambios en los datos de series temporales, que generalmente tienen la misma forma. Hasta ahora he trabajado con el changepointpaquete para R y las funciones cpt.mean(), cpt.var()y cpt.meanvar(). cpt.mean()con el método PELT funciona bien cuando los datos generalmente se mantienen en un nivel. Sin embargo, también me gustaría detectar cambios durante los descensos. Un ejemplo para un cambio, me gustaría detectar, es la sección donde la curva negra cae repentinamente mientras que en realidad debería seguir la línea punteada roja ejemplar. Experimenté con la función cpt.var (), sin embargo, no pude obtener buenos resultados. ¿Tienes alguna recomendación (esas no necesariamente tienen que usar R)?

Cambiar curva

Aquí están los datos con el cambio (como objeto R):

dat.change <- c(12.013995263488, 11.8460207231808, 11.2845153487846, 11.7884417180764, 
11.6865425802022, 11.4703118125303, 11.4677576899063, 11.0227199625084, 
11.274775836817, 11.03073498338, 10.7771805591742, 10.7383206158923, 
10.5847230134625, 10.2479315651441, 10.4196381241735, 10.467607842288, 
10.3682422713283, 9.7834431752935, 9.76649842404295, 9.78257968297228, 
9.87817694914062, 9.3449034905713, 9.56400153361727, 9.78120084558148, 
9.3445162813738, 9.36767436354887, 9.12070987223648, 9.21909859069157, 
8.85136359917466, 8.8814423003979, 8.61830163359642, 8.44796977628488, 
8.06957847272046, 8.37999165387824, 7.98213210294954, 8.21977468333673, 
7.683960439316, 7.73213584532496, 7.98956476021092, 7.83036046746187, 
7.64496198988985, 4.49693528397253, 6.3459274845112, 5.86993447552116, 
4.58301192892403, 5.63419551523625, 6.67847511602895, 7.2005344054883, 
5.54970477623895, 6.00011922569104, 6.882667104467, 4.74057284230894, 
6.2140437333397, 6.18511450451019, 5.83973575417525, 6.57271194428385, 
5.36261938326723, 5.48948831338016, 4.93968645996861, 4.52598133247377, 
4.56372558828803, 5.74515428123725, 5.45931581984165, 5.58701112949141, 
6.00585679276365, 5.41639695946931, 4.55361875158434, 6.23720558202826, 
6.19433060301002, 5.82989415940829, 5.69321394985076, 5.53585871082265, 
5.42684812413063, 5.80887522466946, 5.56660158483312, 5.7284521523444, 
5.25425775891636, 5.4227645808924, 5.34778016248718, 5.07084809927736, 
5.324066161355, 5.03526881241705, 5.17387528516352, 5.29864121433813, 
5.36894461582415, 5.07436929444317, 4.80619983525015, 4.42858947882894, 
4.33623051506001, 4.33481791951228, 4.38041031792294, 3.90012900415342, 
4.04262777674943, 4.34383842876647, 4.36984816425014, 4.11641092254315, 
3.83985887104645, 3.81813419810962, 3.85174630901311, 3.66434598962311, 
3.4281724860426, 2.99726515704766, 2.96694634792395, 2.94003031547181, 
3.20892607367132, 3.03980832743458, 2.85952185077593, 2.70595278908964, 
2.50931109659839, 2.1912274016859)
mlee
fuente
Tenga en cuenta que si solo está solicitando el código R, eso estaría fuera de tema aquí. Si está pidiendo asesoramiento metodológico general, está bien. Puede venir con algún código R, pero de nuevo, puede que no.
gung - Restablece a Monica
1
Buen comentario, estoy interesado en una solución general, usar R sería conveniente.
mlee

Respuestas:

17

Puede usar la detección de valores atípicos de series temporales para detectar cambios en las series temporales. Los procedimientos de Tsay o Chen y Liu son métodos populares de detección de valores atípicos de series temporales. Vea mi pregunta anterior en este sitio.

El paquete tsoutlier de R utiliza el método de Chen y Liu para detectar valores atípicos. SAS / SPSS / Autobox también puede hacer esto. Consulte a continuación el código R para detectar cambios en las series temporales.

library("tsoutliers")
dat.ts<- ts(dat.change,frequency=1)
data.ts.outliers <- tso(dat.ts)
data.ts.outliers
plot(data.ts.outliers)

La función tso en el paquete tsoultlier identifica los siguientes valores atípicos. Puede leer la documentación para averiguar el tipo de valores atípicos.

Outliers:
  type ind time coefhat   tstat
1   TC  42   42 -2.9462 -10.068
2   AO  43   43  1.0733   4.322
3   AO  45   45 -1.2113  -4.849
4   TC  47   47  1.0143   3.387
5   AO  51   51  0.9002   3.433
6   AO  52   52 -1.3455  -5.165
7   AO  56   56  0.9074   3.710
8   LS  62   62  1.1284   3.717
9   AO  67   67 -1.3503  -5.502

El paquete también ofrece buenas parcelas. vea abajo. La trama muestra dónde están los valores atípicos y también qué hubiera pasado si no hubiera valores atípicos.

ingrese la descripción de la imagen aquí

También he usado el paquete R llamado strucchange para detectar cambios de nivel. Como ejemplo en tus datos

library("strucchange")
breakpoints(dat.ts~1)

El programa identifica correctamente los puntos de interrupción o los cambios estructurales.

Optimal 4-segment partition: 

Call:
breakpoints.formula(formula = dat.ts ~ 1)

Breakpoints at observation number:
17 41 87 

Corresponding to breakdates:
17 41 87 

Espero que esto ayude

pronosticador
fuente
1
Gracias, tsofunciona bien, sin embargo, es un poco lento para conjuntos de datos más grandes. Las posiciones de punto de ruptura del cambio de estructura parecen un poco arbitrarias (excepto la posición 41).
Mlee
7

Abordaría este problema desde las siguientes perspectivas . Estas son solo algunas ideas fuera de mi cabeza; tómalas con un grano de sal. Sin embargo, espero que esto sea útil.

  • Agrupación de series de tiempo . Por ejemplo, mediante el uso de la deformación dinámica del tiempo popular (DTW) o enfoques alternativos. Consulte mis respuestas relacionadas: en DTW para clasificación / agrupamiento y en DTW o alternativas para series de tiempo desiguales . La idea es agrupar series de tiempo en categorías "normales" y "anormales" (o similares).

  • Medidas de entropía . Vea mi respuesta relevante sobre las medidas de entropía de series temporales . La idea es determinar la entropía de una serie temporal "normal" y luego compararla con otras series temporales (esta idea supone una desviación de la entropía en caso de desviación de la "normalidad").

  • Detección de anomalías . Vea mi respuesta relevante sobre la detección de anomalías (incluye recursos R). La idea es detectar anomalías directamente a través de varios métodos (ver referencias). La caja de herramientas y el Rpaquete de señales de advertencia temprana (EWS)earlywarnings parecen especialmente prometedores.

Aleksandr Blekh
fuente
6

Mi respuesta usando AUTOBOX es bastante similar a @forecaster pero con un modelo mucho más simple. Box y Einstein y otros han reflexionado sobre cómo mantener las soluciones simples pero no demasiado simples. El modelo que se desarrolló automáticamente fue ingrese la descripción de la imagen aquí. La trama actual y limpia es muy similar ingrese la descripción de la imagen aquí. Aquí se ingrese la descripción de la imagen aquíincluye un gráfico de los residuos (que siempre se debe mostrar) junto con el acf obligatorio de los residuos ingrese la descripción de la imagen aquí. Las estadísticas de los residuos son siempre útiles para hacer comparaciones entre "modelos de duelo" ingrese la descripción de la imagen aquí. El gráfico Actual / Ajuste / Pronóstico está aquíingrese la descripción de la imagen aquí

IrishStat
fuente
1

Parecería que su problema se simplificaría enormemente si desvinculara sus datos. Parece disminuir linealmente. Una vez que elimine los datos, puede aplicar una amplia variedad de pruebas para no estacionariedad.

MrMeritology
fuente
3
Este enfoque fallará porque hay pendientes claramente diferentes en la historia. A menos que esté incorporando múltiples "tendencias / pendientes", este enfoque no producirá resultados significativos. Las soluciones simples y directas a menudo son demasiado simples.
IrishStat
1

Todas son buenas respuestas, pero aquí hay una simple, como lo sugiere @MrMeritology, que parece funcionar bien para la serie de tiempo en cuestión, y probablemente para muchos otros conjuntos de datos "similares".

Aquí hay un fragmento R que produce los gráficos autoexplicativos a continuación.

outl = rep( NA, length(dat.change))
detr = c( 0, diff( dat.change))

ix = abs(detr) > 2*IQR( detr)
outl[ix] = dat.change[ix]

plot( dat.change, t='l', lwd=2, main="dat.change TS")
points( outl, col=2, pch=18)

plot( detr, col=4, main="detrended TS", t='l', lwd=2 )
acf( detr, main="ACF of detrended TS")

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

dnqxt
fuente
puede haber múltiples cambios de tendencia y múltiples cambios de intercepción (cambios de nivel) ... por lo tanto, uno necesita encontrar soluciones que realmente diagnostiquen los datos para determinar estos ...
IrishStat
Sí, de hecho, he leído tu comentario anterior arriba. Sin embargo, diagnosticar la serie temporal para detectar múltiples tendencias / niveles es un problema en sí mismo. Mi punto aquí es mostrar que el enfoque simple anterior funciona a veces, en particular para los datos dados. Por el contrario, ningún enfoque único funcionará bien siempre. Un enfoque de R.Hyndman (tsoutliers con función R) es algo que recomendaría.
dnqxt
AUTOBOX es el enfoque único que funcionará bien siempre (al menos para los miles de millones de series de tiempo que hemos visto) y hay una versión R. Si desea chatear sin conexión ya que no quiero llegar a "salesy" aquí, puedo explicarle el proceso, que es totalmente comprensible / transparente pero no se duplica fácilmente.
IrishStat