Wykrywanie zmian w szeregach czasowych (przykład R)

18

Chciałbym wykryć zmiany w danych szeregów czasowych, które zwykle mają ten sam kształt. Do tej pory pracowałem z changepointpakietem dla R cpt.mean(), cpt.var()oraz cpt.meanvar()funkcji i . cpt.mean()z metodą PELT działa dobrze, gdy dane zwykle pozostają na jednym poziomie. Chciałbym jednak również wykryć zmiany podczas zjazdów. Przykładem zmiany, którą chciałbym wykryć, jest sekcja, w której czarna krzywa nagle spada, podczas gdy faktycznie powinna podążać za przykładową czerwoną kropkowaną linią. Eksperymentowałem z funkcją cpt.var (), jednak nie mogłem uzyskać dobrych wyników. Czy masz jakieś rekomendacje (te niekoniecznie muszą używać R)?

Zmień krzywą

Oto dane ze zmianą (jako obiekt 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
źródło
Zauważ, że jeśli pytasz tylko o kod R, byłoby to nie na temat tutaj. Jeśli prosisz o ogólne porady metodologiczne, to dobrze. Może pochodzić z kodem R, ale z drugiej strony może nie.
Gung - Przywróć Monikę
1
Dobra uwaga, interesuje mnie ogólne rozwiązanie, użycie R byłoby po prostu wygodne.
mlee

Odpowiedzi:

17

Możesz użyć detekcji wartości odstających szeregu czasowego, aby wykryć zmiany w szeregach czasowych. Tsay's lub Chen i Liu procedury są popularne metody wykrywania odstających szeregów czasowych. Zobacz moje wcześniejsze pytanie na tej stronie.

R's Pakiet tsoutlier wykorzystuje metodę Chen i Liu do wykrywania wartości odstających. SAS / SPSS / Autobox również może to zrobić. Zobacz poniżej kod R do wykrywania zmian w szeregach czasowych.

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

Funkcja tso w pakiecie tsoultlier identyfikuje następujące wartości odstające. Możesz przeczytać dokumentację, aby dowiedzieć się, jakie są wartości odstające.

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

pakiet zapewnia również ładne wykresy. patrz poniżej. Fabuła pokazuje, gdzie są wartości odstające, a także co by się stało, gdyby nie było wartości odstających.

wprowadź opis zdjęcia tutaj

Użyłem również pakietu R o nazwie strucchange do wykrywania przesunięć poziomów. Jako przykład twoich danych

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

Program poprawnie identyfikuje punkty przerwania lub zmiany strukturalne.

Optimal 4-segment partition: 

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

Breakpoints at observation number:
17 41 87 

Corresponding to breakdates:
17 41 87 

Mam nadzieję że to pomoże

Synoptyk
źródło
1
Dzięki, tsodziała dobrze, jednak w przypadku większych zestawów danych jest on nieco powolny. Pozycje punktu przerwania struccchange wydają się nieco arbitralne (z wyjątkiem pozycji 41).
mlee
7

Do tego problemu podchodzę z następujących perspektyw . To tylko niektóre pomysły z mojej głowy - proszę, weź je z odrobiną soli. Niemniej jednak mam nadzieję, że będzie to przydatne.

  • Grupowanie szeregów czasowych . Na przykład za pomocą popularnego dynamicznego dopasowania czasu (DTW) lub alternatywne metody. Proszę zobaczyć moje powiązane odpowiedzi: w sprawie DTW dla klasyfikacji / grupowania oraz w DTW lub alternatywnych dla nierównych szeregów czasowych . Pomysł jest klastra szeregów czasowych do kategorii „normalnych” i „nieprawidłowych” (lub podobne).

  • Środki entropii . Zobacz moją odpowiednią odpowiedź dotyczącą miar entropii szeregów czasowych . Pomysłem jest ustalenie entropia „normalnej” szeregów czasowych, a następnie porównać je z innymi szeregu czasowego (pomysł ten ma założeniu entropii odchylenia w przypadku odchylenia od „normalności”).

  • Wykrywanie anomalii . Zobacz moją odpowiednią odpowiedź na temat wykrywania anomalii (obejmuje zasoby R.). Pomysł jest bezpośrednio wykryć anomalie za pośrednictwem różnych metod (patrz referencje). Zestaw narzędzi i Rpakiet wczesnego ostrzegania (EWS)earlywarnings wydają się szczególnie obiecujące.

Aleksandr Blekh
źródło
6

Moja odpowiedź za pomocą AUTOBOX jest dość podobna do @forecaster, ale z dużo prostszym modelem. Box, Einstein i inni zastanawiali się nad tym, aby rozwiązania były proste, ale niezbyt proste. Był to model, który został opracowany automatycznie wprowadź opis zdjęcia tutaj. Rzeczywista i oczyszczona działka jest bardzo podobna wprowadź opis zdjęcia tutaj. Wykres reszt (który zawsze powinien być pokazany) znajduje się tutaj wprowadź opis zdjęcia tutajwraz z obowiązkowym acf reszt wprowadź opis zdjęcia tutaj. Statystyka reszt jest zawsze przydatna przy porównywaniu „modeli pojedynków” wprowadź opis zdjęcia tutaj. Wykres Rzeczywisty / Dopasowanie / Prognoza jest tutajwprowadź opis zdjęcia tutaj

IrishStat
źródło
1

Wydaje się, że Twój problem zostałby znacznie uproszczony, gdybyś stracił dane. Wydaje się, że spada liniowo. Po wycofaniu danych możesz zastosować szereg testów niestabilności.

MrMeritology
źródło
3
Takie podejście się nie powiedzie, ponieważ w historii istnieją wyraźnie różne stoki. O ile nie uwzględnisz wielu „trendów / stoków” to podejście nie przyniesie znaczących rezultatów. Proste, proste rozwiązania są często zbyt proste.
IrishStat
1

Wszystkie dobre odpowiedzi, ale tutaj jest prosta, jak sugeruje @MrMeritology, która wydaje się działać dobrze dla danych szeregów czasowych i prawdopodobnie dla wielu innych „podobnych” zestawów danych.

Oto fragment kodu R wytwarzający poniższe intuicyjne wykresy.

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

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

dnqxt
źródło
może być wiele zmian trendów i wiele zmian przechwytywania (przesunięcia poziomów) ... dlatego trzeba znaleźć rozwiązania, które faktycznie diagnozują dane, aby je ustalić ...
IrishStat
Tak, rzeczywiście, przeczytałem twój poprzedni komentarz powyżej. Jednak diagnozowanie szeregów czasowych w celu wykrycia wielu trendów / poziomów jest problemem samym w sobie. Chodzi mi o to, aby pokazać, że powyższe proste podejście czasami działa, szczególnie w przypadku danych. I odwrotnie, żadne pojedyncze podejście nie zawsze będzie dobrze działać. Podejście R.Hyndmana (t-outliers z funkcją R) jest czymś, co inaczej poleciłbym.
dnqxt
AUTOBOX to pojedyncze podejście, które zawsze będzie działać dobrze (przynajmniej dla zillionów szeregów czasowych, które widzieliśmy) i jest wersja R. Jeśli chcesz porozmawiać offline, ponieważ nie chcę tutaj wchodzić w „sprzedaż”, mogę wyjaśnić proces, który jest w pełni zrozumiały / przejrzysty, ale nie łatwo go powielić.
IrishStat