Interpolacja brakujących wartości w szeregu czasowym z cyklem sezonowym

Mam szereg czasowy, dla którego chcę inteligentnie interpolować brakujące wartości. Na wartość w określonym czasie ma wpływ trend wielodniowy, a także jego pozycja w cyklu dobowym.

Oto przykład, w którym brakuje dziesiątej obserwacji z myzoo

start <- as.POSIXct("2010-01-01") 
freq <- as.difftime(6, units = "hours") 
dayvals <- (1:4)*10 
timevals <- c(3, 1, 2, 4) 
index <- seq(from = start, by = freq, length.out = 16)
obs <- (rep(dayvals, each = 4) + rep(timevals, times = 4))
myzoo <- zoo(obs, index)
myzoo[10] <- NA

Gdybym miał to zaimplementować, użyłbym pewnego rodzaju ważonej średniej czasów zamknięcia w pobliskich dniach, lub dodać wartość na dzień do linii funkcji dopasowanej do większego trendu, ale mam nadzieję, że tam istnieją już jakieś pakiety lub funkcje, które mają zastosowanie do tej sytuacji?

EDIT: zmodyfikowałem nieco kod, aby wyjaśnić mój problem. Istnieją metody na.*, które interpolują od najbliższych sąsiadów, ale w tym przypadku nie uznają, że brakująca wartość jest w czasie, który jest najniższą wartością dnia. Może rozwiązaniem jest przekształcenie danych do szerokiego formatu, a następnie interpolacja, ale nie chciałbym całkowicie lekceważyć sąsiednich wartości z tego samego dnia. Warto zauważyć że diff(myzoo, lag = 4) zwraca wektor 10 ' S. rozwiązanie może leżeć z pewną kombinacją reshape, na.spline, i diff.inv, ale nie mogę tego rozgryźć.

Oto trzy podejścia, które nie działają: Tutaj wpisz opis obrazka

EDIT2. Obraz wykonany za pomocą poniższego kodu.

myzoo <- zoo(obs, index)
myzoo[10] <- NA # knock out the missing point
plot(myzoo, type="o", pch=16) # plot solid line
points(na.approx(myzoo)[10], col = "red")
points(na.locf(myzoo)[10], col = "blue")
points(na.spline(myzoo)[10], col = "green")
myzoo[10] <- 31 # replace the missing point
lines(myzoo, type = "o", lty=3, pch=16) # dashed line over the gap
legend(x = "topleft", 
       legend = c("na.spline", "na.locf", "na.approx"), 
       col=c("green","blue","red"), pch = 1)
Author: J. Win., 2011-02-11

3 answers

Spróbuj tego:

x <- ts(myzoo,f=4)
fit <- ts(rowSums(tsSmooth(StructTS(x))[,-2]))
tsp(fit) <- tsp(x)
plot(x)
lines(fit,col=2)

Chodzi o użycie podstawowego modelu strukturalnego dla szeregów czasowych, który obsługuje brakującą wartość fine za pomocą filtra Kalmana. Następnie gładkość Kalmana jest używana do oszacowania każdego punktu w szeregu czasowym, w tym każdego pominiętego.

Musiałem przekonwertować Twój obiekt zoo na obiekt ts o częstotliwości 4, Aby użyć struktur. Możesz ponownie zmienić dopasowane wartości z powrotem na zoo.

 17
Author: Rob Hyndman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-11 11:45:22

W tym przypadku, myślę, że chcesz korekty sezonowości w modelu ARIMA. Nie ma tu wystarczająco dużo daty, aby pasować do modelu sezonowego, ale to powinno dać ci początek.

library(zoo)
start <- as.POSIXct("2010-01-01") 
freq <- as.difftime(6, units = "hours") 
dayvals <- (1:4)*10 
timevals <- c(3, 1, 2, 4) 
index <- seq(from = start, by = freq, length.out = 16)
obs <- (rep(dayvals, each = 4) + rep(timevals, times = 4))
myzoo <- myzoo.orig <- zoo(obs, index)
myzoo[10] <- NA

myzoo.fixed <- na.locf(myzoo)

myarima.resid <- arima(myzoo.fixed, order = c(3, 0, 3), seasonal = list(order = c(0, 0, 0), period = 4))$residuals
myzoo.reallyfixed <- myzoo.fixed
myzoo.reallyfixed[10] <- myzoo.fixed[10] + myarima.resid[10]

plot(myzoo.reallyfixed)
points(myzoo.orig)
W moich testach Arma (3, 3) jest naprawdę blisko, ale to tylko szczęście. Przy dłuższych seriach czasowych powinieneś być w stanie skalibrować korektę Sezonową, aby dać dobre prognozy. Dobrze byłoby mieć dobre uprzedzenie, co mechanizmy bazowe zarówno dla sygnału, jak i sezonowej korekty, aby uzyskać lepsza wydajność próbki.
 2
Author: Richard Herron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-11 03:52:37

forecast::na.interp to dobre podejście. Z dokumentacji

Używa interpolacji liniowej dla szeregów niesezonowych i okresowego rozkładu stl z szeregami sezonowymi, aby zastąpić brakujące wartości.

library(forecast)
fit <- na.interp(myzoo)
fit[10]  # 32.5, vs. 31.0 actual and 32.0 from Rob Hyndman's answer

Ten artykuł ocenia kilka metod interpolacji względem szeregów czasu rzeczywistego i stwierdza, że na.interp jest zarówno dokładny, jak i wydajny:

Z implementacji R testowanych w tym artykule, na.interpelacja w sprawie pakietu prognoz i na,Struktury z pakietu zoo wykazały najlepsze wyniki ogólne.

Na.funkcja interp również nie jest dużo wolniejsza niż na,ok [najszybsza Metoda], więc rozkład leessa wydaje się nie być zbyt wymagający pod względem czasu obliczeniowego.

Warto również zauważyć, że Rob Hyndman napisał forecast pakiet i dodał na.interp Po udzieleniu odpowiedzi na to pytanie. Jest prawdopodobne, że na.interp jest poprawa w tym podejściu, mimo że wypadło gorzej w ten przykład (prawdopodobnie ze względu na określenie okresu w StructTS, Gdzie na.interp wylicza go).

 2
Author: Max Ghenis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-24 05:42:44