Détection des changements dans les séries temporelles (exemple R)

18

J'aimerais détecter des changements dans les données de séries chronologiques, qui ont généralement la même forme. Jusqu'à présent, j'ai travaillé avec le changepointpackage pour R et les fonctions cpt.mean(), cpt.var()et cpt.meanvar(). cpt.mean()avec la méthode PELT fonctionne bien lorsque les données restent généralement sur un seul niveau. Cependant, je voudrais également détecter les changements lors des descentes. Un exemple de changement, je voudrais détecter, est la section où la courbe noire baisse soudainement alors qu'elle devrait en fait suivre la ligne pointillée rouge exemplaire. J'ai expérimenté la fonction cpt.var (), mais je n'ai pas pu obtenir de bons résultats. Avez-vous des recommandations (celles-ci ne doivent pas nécessairement utiliser R)?

Changer la courbe

Voici les données avec le changement (comme objet 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
la source
Notez que si vous ne demandez que du code R, ce serait hors sujet ici. Si vous demandez des conseils méthodologiques généraux, c'est bien. Cela pourrait venir avec du code R, mais encore une fois, ce pourrait ne pas l'être.
gung - Rétablir Monica
1
Bonne remarque, je suis intéressé par une solution générale, utiliser R serait tout simplement pratique.
mlee

Réponses:

17

Vous pouvez utiliser la détection des valeurs aberrantes des séries chronologiques pour détecter les changements dans les séries chronologiques. Les procédures de Tsay ou Chen et Liu sont des méthodes de détection des valeurs aberrantes de séries chronologiques populaires. Voir ma question précédente sur ce site.

Le paquet tsoutlier de R utilise la méthode de Chen et Liu pour détecter les valeurs aberrantes. SAS / SPSS / Autobox peut également le faire. Voir ci-dessous pour le code R pour détecter les changements dans les séries chronologiques.

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

La fonction tso dans le package tsoultlier identifie les valeurs aberrantes suivantes. Vous pouvez lire la documentation pour connaître le type de valeurs aberrantes.

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

le package fournit également de belles parcelles. voir ci-dessous. L'intrigue montre où se trouvent les valeurs aberrantes et aussi ce qui se serait produit s'il n'y avait pas de valeurs aberrantes.

entrez la description de l'image ici

J'ai également utilisé le package R appelé strucchange pour détecter les changements de niveau. À titre d'exemple sur vos données

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

Le programme identifie correctement les points d'arrêt ou les changements structurels.

Optimal 4-segment partition: 

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

Breakpoints at observation number:
17 41 87 

Corresponding to breakdates:
17 41 87 

J'espère que cela t'aides

prévisionniste
la source
1
Merci, cela tsofonctionne bien, mais c'est un peu lent pour les grands ensembles de données. Les positions de point d'arrêt du struccchange semblent un peu arbitraires (sauf la position 41).
mlee
7

J'aborderais ce problème sous les angles suivants . Ce ne sont que quelques idées du haut de ma tête - veuillez les prendre avec un grain de sel. J'espère néanmoins que cela sera utile.

  • Regroupement de séries chronologiques . Par exemple, en utilisant la distorsion temporelle dynamique (DTW) ou d'autres approches. Veuillez consulter mes réponses connexes: sur DTW pour la classification / clustering et sur DTW ou alternatives pour les séries chronologiques inégales . L' idée est de regrouper les séries chronologiques en catégories "normales" et "anormales" (ou similaires).

  • Mesures d'entropie . Voir ma réponse pertinente sur les mesures d'entropie de séries chronologiques . L' idée est de déterminer l'entropie d'une série temporelle "normale" puis de la comparer avec d'autres séries temporelles (cette idée suppose une déviation d'entropie en cas d'écart par rapport à la "normalité").

  • Détection d'anomalies . Voir ma réponse pertinente sur la détection d'anomalies (inclut les ressources R). L' idée est de détecter directement les anomalies via différentes méthodes (voir références). La boîte à outils et le Rpackage des signaux d'alerte précoce (EWS)earlywarnings semblent particulièrement prometteurs.

Aleksandr Blekh
la source
6

Ma réponse en utilisant AUTOBOX est assez similaire à @forecaster mais avec un modèle beaucoup plus simple. Box et Einstein et d'autres ont réfléchi à garder les solutions simples mais pas trop simples. Le modèle qui a été développé automatiquement était entrez la description de l'image ici. L'intrigue réelle et nettoyée est très similaire entrez la description de l'image ici. Un tracé des résidus (qui devrait toujours être montré) est ici entrez la description de l'image iciavec l'acf obligatoire des résidus entrez la description de l'image ici. Les statistiques des résidus sont toujours utiles pour faire des comparaisons entre "modèles de duels" entrez la description de l'image ici. Le graphique Actual / Fit / Forecast est icientrez la description de l'image ici

IrishStat
la source
1

Il semblerait que votre problème serait grandement simplifié si vous détrôniez vos données. Elle semble décliner linéairement. Une fois que vous détruisez les données, vous pouvez appliquer une grande variété de tests de non-stationnarité.

MrMeritology
la source
3
Cette approche échouera car il y a clairement des pentes différentes dans l'histoire. À moins que vous n'intégriez plusieurs «tendances / pentes», cette approche ne produira pas de résultats significatifs. Des solutions simples et simples sont souvent trop simples.
IrishStat
1

Toutes les bonnes réponses, mais voici une réponse simple, comme suggéré par @MrMeritology, qui semble bien fonctionner pour la série chronologique en question, et probablement pour de nombreux autres ensembles de données "similaires".

Voici un extrait R produisant les graphiques explicatifs ci-dessous.

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

entrez la description de l'image ici entrez la description de l'image ici entrez la description de l'image ici

dnqxt
la source
il peut y avoir plusieurs changements de tendance et plusieurs changements d'interception (changements de niveau) ... il faut donc trouver des solutions qui diagnostiquent réellement les données pour les déterminer ...
IrishStat
Oui, en effet, j'ai lu votre commentaire précédent ci-dessus. Cependant, le diagnostic de la série chronologique pour détecter plusieurs tendances / niveaux est un problème en soi. Mon point ici est de montrer que l'approche simple ci-dessus fonctionne parfois, en particulier pour les données données. Inversement, aucune approche unique ne fonctionnera toujours bien. Une approche de R.Hyndman (tsoutliers de fonction R) est quelque chose que je recommanderais autrement.
dnqxt
AUTOBOX est l'approche unique qui fonctionnera toujours bien (au moins pour les millions de séries chronologiques que nous avons vues) et il existe une version R. Si vous souhaitez discuter hors ligne car je ne veux pas arriver à "salesy" ici, je peux expliquer le processus qui est entièrement compréhensible / transparent mais pas facilement dupliqué.
IrishStat