Time series. Time series hanyalah serangkaian titik data yang diurutkan dalam waktu. Dalam time series, waktu sering menjadi variabel independen dan tujuannya biasanya untuk membuat ramalan untuk masa depan.
Data time series sering muncul saat memantau proses industri atau melacak metrik bisnis perusahaan. Perbedaan penting antara memodelkan data melalui metode time series atau menggunakan metode proses monitoring.
Analisis time series terdiri dari metode untuk menganalisis data time series untuk mengekstrak statistik yang berarti dan karakteristik data lainnya. Peramalan time series adalah penggunaan model untuk memprediksi nilai masa depan berdasarkan nilai yang diamati sebelumnya.
Sementara analisis regresi sering digunakan sedemikian rupa untuk menguji teori bahwa nilai saat ini dari satu atau lebih time series independen mempengaruhi nilai saat ini dari time series lain, jenis analisis time series ini tidak disebut “analisis time series”, yang berfokus pada membandingkan nilai time series tunggal atau time series bergantung ganda pada titik waktu yang berbeda. Analisis time series terputus adalah analisis intervensi pada time series tunggal.
Analisis Time Series digunakan untuk banyak aplikasi seperti:
and many, many more…
Dalam hal ini kami akan mencoba menggunakan 3 Pemodelan Time Series dan membuat prediksi berdasarkan model.
Pada akhirnya kita akan membandingkan Mean Absolute Percentage Error dari hasil peramalan dari setiap model time series.
library(tidyverse)
library(forecast)
library(lubridate)
library(TTR)
library(MLmetrics)
library(zoo)
library(plotly)
library(xts)
library(TSstudio)
library(tseries)Dalam hal ini kita akan menggunakan paket tsdl The Time Series Data Library. Paket ini berisi data time series dari banyak subjek. Data yang disediakan pada paket ini sudah dikonversi sebagai objek Time Series.
library(tsdl)Periksa jenis subjek di dalam Data Library
tsdl## Time Series Data Library: 648 time series
##
## Frequency
## Subject 0.1 0.25 1 4 5 6 12 13 52 365 Total
## Agriculture 0 0 37 0 0 0 3 0 0 0 40
## Chemistry 0 0 8 0 0 0 0 0 0 0 8
## Computing 0 0 6 0 0 0 0 0 0 0 6
## Crime 0 0 1 0 0 0 2 1 0 0 4
## Demography 1 0 9 2 0 0 3 0 0 2 17
## Ecology 0 0 23 0 0 0 0 0 0 0 23
## Finance 0 0 23 5 0 0 20 0 2 1 51
## Health 0 0 8 0 0 0 6 0 1 0 15
## Hydrology 0 0 42 0 0 0 78 1 0 6 127
## Industry 0 0 9 0 0 0 2 0 1 0 12
## Labour market 0 0 3 4 0 0 17 0 0 0 24
## Macroeconomic 0 0 18 33 0 0 5 0 0 0 56
## Meteorology 0 0 18 0 0 0 17 0 0 12 47
## Microeconomic 0 0 27 1 0 0 7 0 1 0 36
## Miscellaneous 0 0 4 0 1 1 3 0 1 0 10
## Physics 0 0 12 0 0 0 4 0 0 0 16
## Production 0 0 4 14 0 0 28 1 1 0 48
## Sales 0 0 10 3 0 0 24 0 9 0 46
## Sport 0 1 1 0 0 0 0 0 0 0 2
## Transport and tourism 0 0 1 1 0 0 12 0 0 0 14
## Tree-rings 0 0 34 0 0 0 1 0 0 0 35
## Utilities 0 0 2 1 0 0 8 0 0 0 11
## Total 1 1 300 64 1 1 240 3 16 21 648
Dalam hal ini saya akan menggunakan data Sales dengan Frekuensi 12 atau Bulanan. Kita perlu mensubsetnya
sales <- subset(tsdl, 'sales', 12)
sales <- sales[[24]]head(sales)## Time Series:
## Start = 1966.83
## End = 1967.24666666667
## Frequency = 12
## [1] 61 48 53 78 75 58
## attr(,"source")
## [1] Roberts (1992)
## attr(,"description")
## [1] Monthly unit sales, Winnebago Industries, Nov. 1966 – Feb. 1972
## attr(,"subject")
## [1] Sales
Data Time Series kami dapatkan dari tsdl sebelum kami akan memeriksa apakah ada NA di dalam data.
# Length of data
length(sales)## [1] 64
# NA check
table(is.na(sales))##
## FALSE
## 64
Kita bisa melihat total panjang data 64 dan kita mendapatkan FALSE 64, artinya data tidak memiliki NA. Tidak hanya NA yang harus kita periksa, kita coba untuk mengetahui bagaimana distribusi dari data time series kita. kita bisa menggunakan sintaks summary untuk mengetahui distribusi data kita.
summary(sales)## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 48.0 194.5 371.0 466.8 628.0 1753.0
Min data time series kami adalah 48,0 itu berarti data kami tidak memiliki nilai 0.
Dari data paket tsdl kita sudah mendapatkannya sebagai objek TS. Ini adalah vektor atau matriks dengan kelas “ts” (dan atribut tambahan) yang mewakili data yang telah diambil sampelnya pada titik waktu yang sama. Dalam kasus matriks, setiap kolom data matriks diasumsikan berisi satu time series (univariat). Time series harus memiliki setidaknya satu pengamatan, dan meskipun tidak harus numerik, ada dukungan yang sangat terbatas untuk deret non-numerik.
Saya akan mencoba membalikkannya ke data frame, ini dapat membantu kita untuk memvisualisasikan data nanti.
sales_df <- data.frame(Y = as.matrix(sales), date = as_date(yearmon(time(sales))))Pada sub bagian ini, saya akan mencoba untuk mengeksplorasi objek time series. Kami akan mencoba untuk lebih memahami objek kami, apakah kami dapat menemukan trend, seassonal, atau interpretasi atau wawasan lain berdasarkan visualisasi.
Pada dasarnya ada dua metode untuk menganalisis Seasonality dari time series: additive and multiplicative. dan untuk mengkategorikan objek Time Series terdapat 3 komponen utama yang akan diperhitungkan untuk peramalan. Komponen-komponen ini adalah:
Synthetically it is a model of data in which the effects of the individual factors are differentiated and added to model the data. It can be represented by:
\(y(t) = Trend + Seasonality + Noise\)
In the additive model, the behavior is linear where changes over time are consistently made by the same amount, like a linear trend. In this situation, the linear seasonality has the same amplitude and frequency.
In this situation, trend and seasonal components are multiplied and then added to the error component. It is not linear, can be exponential or quadratic and represented by a curved line as below:
\(y(t) = Trend * Seasonality * Noise\)
Different from the additive model, the multiplicative model has an increasing or decreasing amplitude and/or frequency over time.
These charts can summarize Additive Model and Multiplicative Model
Selanjutnya kita akan mencoba memvisualisasikan objek time series kita untuk mengetahui apakah multiplicative atau additive
ggplotly(
sales %>% as.xts() %>% autoplot() + theme_bw()
) Berdasarkan grafik kita dapat mengatakan data kita Multiplicative karena menunjukkan perilaku bertindak sebagai corong yang meningkat.
Pada bagian ini kita akan mencoba mendekomposisi data, artinya kita akan mencoba memisahkan 3 komponen yaitu Trend, Seasonality dan Error
sales_deco <- decompose(sales, type = "multiplicative")Visualise trend data
sales_deco$trend %>% autoplot()Kami menemukan bahwa trand kami sudah lancar dan tidak ada tampilan seasonality lain, jadi itu berarti pengaturan seasonal dan frekuensi kami di objek ts telah dipasang dengan baik dan kami dapat menyebutnya single seasonal.
next, visualise seasonal
sales_deco$seasonal %>% autoplot()Kita dapat mengatakan pola seasonal tangkapan kita terurai dengan baik, karena menunjukkan pola yang berulang dengan jangka waktu yang tetap/sama. kita bisa mencoba lebih berintegrasi berdasarkan seasonal, mari kita coba mengolah datanya.
sales_df %>%
mutate(
seasonal = sales_deco$seasonal,
date = month(ymd(date), label = T, abbr = F)
) %>%
distinct(date, seasonal) %>%
ggplot(mapping = aes(x = date, y = seasonal)) +
geom_col() +
theme_bw()Berdasarkan plot, kita dapat mengasumsikan sales mulai meningkat mulai dari Januari hingga pertengahan tahun, dan akan menurun mulai dari pertengahan tahun hingga Desember.
Cross Validation untuk time series tidak boleh diambil sampelnya secara acak, tetapi dipisah secara berurutan. dalam hal ini kami akan mengambil 12 data terakhir sebagai data uji dan menyimpan data lainnya sebagai data kereta
sales_train <- head(sales, length(sales) - 12)
sales_test <- tail(sales, 12)Simple Moving Average mungkin merupakan pendekatan yang paling naif untuk pemodelan time series. Model ini hanya menyatakan bahwa pengamatan berikutnya adalah rata-rata dari semua pengamatan sebelumnya.
sales_sma <- SMA(x = sales_train, n = 6)sales_sma## Time Series:
## Start = 1966.83
## End = 1971.08
## Frequency = 12
## [1] NA NA NA NA NA 62.16667 76.33333
## [8] 100.50000 112.33333 119.33333 129.16667 136.00000 133.33333 128.83333
## [15] 136.16667 160.66667 190.66667 246.16667 283.66667 320.00000 330.66667
## [22] 325.33333 321.83333 290.16667 272.33333 247.66667 243.83333 264.33333
## [29] 274.16667 301.50000 353.83333 379.33333 413.83333 436.33333 445.83333
## [36] 432.83333 376.16667 343.83333 300.50000 291.50000 335.16667 426.16667
## [43] 482.16667 553.16667 631.83333 667.33333 638.00000 549.66667 524.16667
## [50] 518.33333 480.83333 488.83333
autoplot(sales_train) +
autolayer(sales_sma) +
theme_minimal()Dalam plot di atas, kami menerapkan model simple moving averange ke jendela bulanan. Garis merah merapikan time series. Kami sudah memiliki model SMA dan kami akan memperkirakan menggunakan forecast dan data panjang yang kami duga adalah panjang dari data [sales_test] kami.
sales_sma_forecast <- forecast(sales_sma, h = length(sales_test))Kami mencoba untuk memplotnya, seperti yang kami tahu model ini akan memuluskan data histori yang pada akhirnya akan digunakan untuk meramalkan. kita bisa merencanakannya seperti ini
plot_forecast(sales_sma_forecast)Namun plot pengamatan di atas adalah dari model, kita dapat melihat data nyata dibandingkan dengan perkiraan kita.
sales_train %>% autoplot() +
autolayer(sales_sma_forecast) +
theme_bw()Terakhir kami dapat membandingkan data peramalan kami dengan data pengujian kami, dan kami mengevaluasinya menggunakan MAPE, kami menemukan bahwa Kesalahan kami adalah sekitar 31,2%
result <- MAPE(y_pred = sales_sma_forecast$mean, y_true = sales_test)*100
result## [1] 31.21606
result_mape <- data.frame(
"Model" = "Simple Moving Average",
"MAPE" = round(result)
)Exponential smoothing menggunakan logika yang mirip dengan moving average, tetapi kali ini, bobot penurunan yang berbeda diberikan untuk setiap pengamatan. Dengan kata lain, observasi menjadi kurang penting saat kita bergerak lebih jauh dari masa kini.
Exponential smoothing method dibagi menjadi 3 type:
Jadi berdasarkan analisis data Eksplorasi kami sebelumnya, kami tahu bahwa data memiliki trend dan seasonal. Metode yang akan kita gunakan dalam hal ini adalah [Holt Winters] atau Triple Exponential Smoothing
Metode ini memperluas double exponential smoothing, dengan menambahkan faktor seasonal smoothing. Kami tahu bahwa pola seasonal kami adalah Multiplicative, tetapi dalam kasus ini saya akan mencoba melakukan keduanya seasonal dan untuk mengetahui lebih banyak hasilnya
# using HoltWinters function to make model and using "additive" for seasonal setup
sales_triple_ex_add <- HoltWinters(x = sales_train, seasonal = "additive")
sales_triple_ex_add## Holt-Winters exponential smoothing with trend and additive seasonal component.
##
## Call:
## HoltWinters(x = sales_train, seasonal = "additive")
##
## Smoothing parameters:
## alpha: 0.5265989
## beta : 0
## gamma: 0
##
## Coefficients:
## [,1]
## a 618.748592
## b 15.946241
## s1 55.288194
## s2 160.704861
## s3 34.954861
## s4 74.163194
## s5 -4.545139
## s6 -21.211806
## s7 -25.045139
## s8 -85.586806
## s9 -78.878472
## s10 -59.545139
## s11 -70.003472
## s12 19.704861
# using HoltWinters function to make model and using "multiplicative" for seasonal setup
sales_triple_ex_multi <- HoltWinters(x = sales_train, seasonal = "multiplicative")
sales_triple_ex_multi## Holt-Winters exponential smoothing with trend and multiplicative seasonal component.
##
## Call:
## HoltWinters(x = sales_train, seasonal = "multiplicative")
##
## Smoothing parameters:
## alpha: 0.2641399
## beta : 0
## gamma: 0.2420101
##
## Coefficients:
## [,1]
## a 698.2807712
## b 15.9462413
## s1 1.2246027
## s2 1.5330102
## s3 1.3123347
## s4 1.4233987
## s5 1.0185449
## s6 0.9477492
## s7 0.8519777
## s8 0.5762602
## s9 0.6458062
## s10 0.7199728
## s11 0.6129171
## s12 1.0530772
beberapa argumen berdasarkan hasil di atas
Setelah kami membuat model, kami dapat menggunakan model tersebut untuk forecast menggunakan data train_sales:
forecast_triple_ex_multi <- forecast(object = sales_triple_ex_multi, h = length(sales_test))
forecast_triple_ex_add <- forecast(object = sales_triple_ex_add, h = length(sales_test))forecast_triple_ex_multi## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## 1971.163 874.6443 815.2322 934.0564 783.7813 965.5073
## 1971.247 1119.3630 1045.1790 1193.5471 1005.9084 1232.8177
## 1971.330 979.1585 902.3545 1055.9625 861.6970 1096.6201
## 1971.413 1084.7234 996.4155 1173.0313 949.6681 1219.7786
## 1971.497 792.4402 712.6889 872.1915 670.4711 914.4093
## 1971.580 752.4732 668.3852 836.5613 623.8717 881.0748
## 1971.663 690.0205 603.9452 776.0958 558.3796 821.6614
## 1971.747 475.9049 399.2199 552.5900 358.6253 593.1846
## 1971.830 543.6376 453.8387 633.4366 406.3020 680.9732
## 1971.913 617.5517 513.9650 721.1385 459.1295 775.9740
## 1971.997 535.4992 437.2101 633.7883 385.1790 685.8194
## 1972.080 936.8551 789.1004 1084.6097 710.8838 1162.8263
Setelah mendapatkan perkiraan hasil, kami dapat memvisualisasikannya dan membandingkan hasil perkiraan dengan data test_sales.
test_forecast(actual = sales, # data keseluruhan
forecast.obj = forecast_triple_ex_multi, # hasil object forecast
train = sales_train, # data train
test = sales_test) # data testtest_forecast(actual = sales, # data keseluruhan
forecast.obj = forecast_triple_ex_add, # hasil object forecast
train = sales_train, # data train
test = sales_test) # data testTerakhir kami dapat membandingkan data peramalan kami dengan data pengujian kami, dan kami mengevaluasinya menggunakan MAPE, kami menemukan bahwa Kesalahan kami adalah sekitar 26% untuk Multiplicative dan 36% untuk Additive
# Calculate MAPE for each holts winters
result_multi <- MAPE(y_pred = forecast_triple_ex_multi$mean, y_true = sales_test)*100
result_add <- MAPE(y_pred = forecast_triple_ex_add$mean, y_true = sales_test)*100
# Result of MAPE
result_multi## [1] 26.15384
result_add## [1] 31.91561
# Binding result to compare with other modelling
result <- data.frame(
"Model" = c("Holts Winter Additive", "Holts Winter Multiplicative"),
"MAPE" = c(round(result_add),round(result_multi))
)
result_mape <- rbind(result_mape, result)Meskipun metode eksponensial smoothing tidak membuat asumsi apa pun tentang korelasi antara nilai-nilai berurutan dari time series, dalam beberapa kasus Anda dapat membuat model prediksi yang lebih baik dengan mempertimbangkan korelasi dalam data. Model Autoregressive Integrated Moving Average (ARIMA) menyertakan model statistik eksplisit untuk komponen tak beraturan dari time series, yang memungkinkan autokorelasi bukan nol pada komponen tak beraturan.
Model ARIMA didefinisikan untuk time series stasioner. Oleh karena itu, jika kita memulai dengan times series yang tidak stasioner, perlu ‘membedakan’ time series tersebut sampai kita mendapatkan time series yang stasioner.
Kami memeriksa data time series kami, apakah itu stasioner?
H0: Data not stationary H1: Data stationary
We will reject H0 if p-value < 0.05
adf.test(x = sales)##
## Augmented Dickey-Fuller Test
##
## data: sales
## Dickey-Fuller = -3.1705, Lag order = 3, p-value = 0.1007
## alternative hypothesis: stationary
Hasil p-value dari data kita adalah 0,100 artinya kita menerima H0 dan data kita tidak stasioner. Kami akan mencoba 1 kali differencing menggunakan fungsi diff
# attempt 1 times diff
adf.test(diff(sales))## Warning in adf.test(diff(sales)): p-value smaller than printed p-value
##
## Augmented Dickey-Fuller Test
##
## data: diff(sales)
## Dickey-Fuller = -6.0575, Lag order = 3, p-value = 0.01
## alternative hypothesis: stationary
Hasilnya kita hanya perlu 1 kali differencing untuk membuat data kita stasioner. Bisa jadi model dasar kita bahwa model optimal kita hanya membutuhkan 1 kali differencing.
Kami membuat model ARIMA menggunakan fungsi auto.arima, fungsi otomatis ini akan memberikan hasil yang optimal dari model arima.
sales_arima_auto <- auto.arima(y = sales_train)
summary(sales_arima_auto)## Series: sales_train
## ARIMA(0,1,0)
##
## sigma^2 estimated as 13345: log likelihood=-314.59
## AIC=631.18 AICc=631.26 BIC=633.11
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 12.28963 114.4049 80.86656 -0.2405419 24.24669 0.5348317
## ACF1
## Training set -0.1110519
Model yang kita peroleh adalah ARIMA(0,1,0), seperti yang kita prediksi sebelum differencing optimum adalah 1, kita bisa melihatnya dari ARIMA(p,d,q) sehingga differencing berdasarkan model adalah d = 1.
kami akan memperkirakan menggunakan model dan lihat hasilnya
forecast_arima_auto <- forecast(sales_arima_auto, h = length(sales_test))plot_forecast(forecast_arima_auto)Kami membandingkan data peramalan kami dengan data pengujian kami, dan kami mengevaluasinya menggunakan MAPE, kami menemukan bahwa Kesalahan kami sekitar 32%
result_arima <- MAPE(y_pred = forecast_arima_auto$mean, y_true = sales_test)*100
# Result of MAPE
result_arima## [1] 32.85827
# Binding result to compare with other modelling
result <- data.frame(
"Model" = c("ARIMA"),
"MAPE" = c(round(result_arima))
)
result_mape <- rbind(result_mape, result)Setelah didapatkan hasil dari masing-masing model Moving Average, Exponential Smooting, dan ARIMA. Kami mencoba untuk memeriksa asumsi.
Fungsi yang kita gunakan dalam pengecekan ini adalah shapiro.test dan dalam pengecekan ini diharapkan menerima H0 karena pvalue > 0.05
H0 : residuals are normally distributed
H1 : residuals are not normally distributed
# SMA Model
shapiro.test(sales_sma_forecast$residuals)##
## Shapiro-Wilk normality test
##
## data: sales_sma_forecast$residuals
## W = 0.95148, p-value = 0.04952
# Triple Exponential Smooting with Multiplicative Seasonal
shapiro.test(forecast_triple_ex_multi$residuals)##
## Shapiro-Wilk normality test
##
## data: forecast_triple_ex_multi$residuals
## W = 0.97929, p-value = 0.6632
# Triple Exponential Smooting with Additive Seasonal
shapiro.test(forecast_triple_ex_add$residuals)##
## Shapiro-Wilk normality test
##
## data: forecast_triple_ex_add$residuals
## W = 0.96391, p-value = 0.2273
# ARIMA Model
shapiro.test(forecast_arima_auto$residuals)##
## Shapiro-Wilk normality test
##
## data: forecast_arima_auto$residuals
## W = 0.96444, p-value = 0.122
Hasil dari 4 model yang kami periksa, hanya simple moving average yang memiliki p-value < 0,05 artinya residual tidak berdistribusi normal
Kami ingin memeriksa no-autokorelasi, kami akan menggunakan fungsi Box.test
H0 : No autocorrelation in the forecast errors H1 : there is an autocorrelation in the forecast errors
We expect p-value from our model is > 0.05 to accept H0
# SMA Model
Box.test(x = sales_sma_forecast$residuals)##
## Box-Pierce test
##
## data: sales_sma_forecast$residuals
## X-squared = 2.1206, df = 1, p-value = 0.1453
# Triple Exponential Smooting with Multiplicative Seasonal
Box.test(x = forecast_triple_ex_multi$residuals)##
## Box-Pierce test
##
## data: forecast_triple_ex_multi$residuals
## X-squared = 1.182, df = 1, p-value = 0.277
# Triple Exponential Smooting with Additive Seasonal
Box.test(x = forecast_triple_ex_add$residuals)##
## Box-Pierce test
##
## data: forecast_triple_ex_add$residuals
## X-squared = 0.49319, df = 1, p-value = 0.4825
# ARIMA Model
Box.test(x = forecast_arima_auto$residuals)##
## Box-Pierce test
##
## data: forecast_arima_auto$residuals
## X-squared = 0.64129, df = 1, p-value = 0.4232
Berdasarkan hasil, semua model kami p-value > 0,05 artinya semua model kami tidak memiliki autokorelasi dalam kesalahan perkiraan
Mari kita lihat tabel hasil MAPE kita dari semua model yang kita buat sebelumnya
result_mape## Model MAPE
## 1 Simple Moving Average 31
## 2 Holts Winter Additive 32
## 3 Holts Winter Multiplicative 26
## 4 ARIMA 33