Dalam dunia analisis data, peramalan (forecasting) menjadi salah satu topik yang penting, terutama ketika kita berhadapan dengan data deret waktu (time series). Banyak sektor mulai dari ekonomi, pertanian, energi, hingga teknologi, bergantung pada kemampuan untuk memprediksi nilai masa depan berdasarkan pola historis.
Di ekosistem R, kita mengenal berbagai pendekatan klasik seperti ARIMA, ETS, dan TBATS yang tersedia dalam paket seperti forecast. Namun, seiring berkembangnya kebutuhan dan kemunculan model machine learning serta deep learning, muncul kebutuhan akan framework yang lebih fleksibel, terintegrasi, dan mudah diatur untuk berbagai jenis model time series.
Pada tulisan ini, kita akan membahas bagaimana cara kerja
modeltime, komponen utamanya, serta bagaimana paket ini
dapat mempercepat proses pengembangan model forecasting yang
reproducible dan scalable.
Alur kerja modeltime, seperti dikutip dari situs web CRAN-R, terdiri dari langkah-langkah berikut:
Mengumpulkan data dan membaginya menjadi data pelatihan (training set) dan data pengujian (test set).
Membuat dan menyesuaikan (fit) beberapa model.
Menambahkan model yang telah disesuaikan ke dalam Model Table.
Melakukan kalibrasi model terhadap data pengujian.
Melakukan peramalan (forecast) pada data pengujian dan evaluasi akurasi.
Melatih ulang (refit) model menggunakan seluruh dataset dan melakukan peramalan ke depan.
Kita panggil data yang akan digunakan dalam tulisan ini. Data bisa didownload di website BPS Lampung.
# load library
library(tidymodels)
library(modeltime)
library(tidyverse)
library(xgboost)
library(prophet)
library(timetk)
# load data
data <- readxl::read_excel('prod_lpg_.xlsx')
head(data)## # A tibble: 6 × 2
## bulan lampung
## <dttm> <dbl>
## 1 2018-01-01 00:00:00 114130.
## 2 2018-02-01 00:00:00 148112.
## 3 2018-03-01 00:00:00 323383.
## 4 2018-04-01 00:00:00 554272.
## 5 2018-05-01 00:00:00 260567.
## 6 2018-06-01 00:00:00 127379.
Data terdiri dari 2 variabel, yaitu bulan dan lampung. Data ini
merupakan data produksi padi bulanan yang dihasilkan dari kegiatan
survei Kerangka Sampel Area (KSA) Padi di seluruh kabupaten/kota
se-Lampung. Jadi data ini merupakan data agregasi di level provinsi.
Plot deret waktu produksi padi bulanan menunjukkan pola yang fluktuatif dengan kecenderungan musiman yang kuat. Setiap tahun tampak adanya periode puncak produksi yang tinggi, diikuti oleh penurunan tajam pada bulan-bulan berikutnya, yang mengindikasikan adanya siklus panen dan masa tanam yang berulang secara teratur.
Meskipun terjadi variasi yang cukup besar dari bulan ke bulan, garis
tren berwarna biru memperlihatkan bahwa secara keseluruhan terdapat
kecenderungan peningkatan produksi dari tahun 2021 hingga 2025, setelah
sempat mengalami penurunan ringan pada periode awal 2018–2020. Pola ini
menggambarkan bahwa produktivitas padi secara umum mengalami perbaikan
dalam jangka panjang, meskipun masih dipengaruhi oleh faktor musiman dan
variabilitas tahunan yang tinggi.
Modeltime mengakomodir berbagai model yang dapat
digunakan.
Model 1: Auto ARIMA
Kita buat model dasar Auto ARIMA:
# Model 1: auto_arima ----
model_fit_arima_no_boost <- arima_reg() %>%
set_engine(engine = "auto_arima") %>%
fit(lampung ~ bulan, data = training(splits))Model 2: Boosted Auto ARIMA
Model arima_boost() menggabungkan dua pendekatan, yaitu
ARIMA dan XGBoost, untuk meningkatkan
akurasi peramalan deret waktu. ARIMA digunakan untuk menangkap pola
linear berdasarkan urutan waktu, sedangkan XGBoost mempelajari residual
(kesalahan) dari ARIMA untuk menangani pola non-linear yang tidak bisa
dijelaskan oleh ARIMA. Dalam model ini, fitur tanggal
(bulan) digunakan oleh ARIMA sebagai penanda waktu,
sementara turunan dari bulan, kuartal, atau hari dalam minggu digunakan
oleh XGBoost sebagai variabel tambahan (regressor).
Agar fitur waktu tersebut dapat dibuat secara efisien, gunakan fungsi
step_timeseries_signature() dari paket timetk.
Fungsi ini secara otomatis mengekstrak berbagai komponen waktu dari
variabel tanggal, seperti tahun, bulan, kuartal, dan sebagainya,
sehingga memudahkan proses pemodelan tanpa harus menulis formula yang
kompleks. Dengan cara ini, arima_boost() dapat memanfaatkan
kekuatan ARIMA dalam menangkap tren linear sekaligus kekuatan XGBoost
dalam mengenali pola non-linear pada data time series.
# Model 2: arima_boost ----
model_fit_arima_boosted <- arima_boost(
min_n = 2,
learn_rate = 0.015
) %>%
set_engine(engine = "auto_arima_xgboost") %>%
fit(lampung ~ bulan + as.numeric(bulan) + factor(month(bulan, label = TRUE), ordered = F),
data = training(splits))Model 3: Exponential Smoothing
Kita buat model Error-Trend Seasonal menggunakan model Exponential Smoothing State Space.
# Model 3: ets ----
model_fit_ets <- exp_smoothing() %>%
set_engine(engine = "ets") %>%
fit(lampung ~ bulan, data = training(splits))Model 4: Prophet
# Model 4: prophet ----
model_fit_prophet <- prophet_reg() %>%
set_engine(engine = "prophet") %>%
fit(lampung ~ bulan, data = training(splits))Model 5: Linear Regression
Model ini menjelaskan nilai deret waktu sebagai kombinasi dari tren waktu (linear) dan musiman (periodik). Linear regression menggunakan 2 jenis informasi dari variabel bulan, yaitu:
Trend dimodelkan sebagai as.numeric(bulan), artinya
bulan diubah menjadi angka. Halini memungkinkan model menangkap arah
trend jangka panjang apakah nilai datanya cenderung naik atau cenderung
turun seiring berjalannya waktu.
Seasonal dimodelkan dengan month(bulan), yaitu bulan
diambil dari variabel tersebut untuk merepresentasikan pola musiman,
misalnya produksi padi meningkat pada bulan-bulan tertentu setiap
tahun.
# Model 5: lm ----
model_fit_lm <- linear_reg() %>%
set_engine("lm") %>%
fit(lampung ~ as.numeric(bulan) + factor(month(bulan, label = TRUE), ordered = FALSE),
data = training(splits))Setelah model selesai dibuat dan di-fit pada data, langkah berikutnya adalah menggabungkan semua model tersebut ke dalam satu wadah menggunakan fungsi modeltime_table(). Fungsi ini akan memeriksa apakah setiap model sudah dilatih dengan benar, lalu menyusunnya dalam struktur terorganisir yang disebut “Modeltime Table”.
Struktur ini berguna karena memudahkan kita untuk melakukan proses lanjutan seperti evaluasi performa, kalibrasi, atau membuat peramalan terhadap banyak model sekaligus secara efisien dan terukur. Jadi, modeltime_table() berfungsi sebagai tempat penyimpanan dan pengelolaan model-model time series dalam satu workflow yang rapi dan scalable.
models_tbl <- modeltime_table(
model_fit_arima_no_boost,
model_fit_arima_boosted,
model_fit_ets,
model_fit_prophet,
model_fit_lm
)Ketika kita melakukan kalibrasi model, fungsi modeltime_calibrate()
akan menambahkan kolom baru bernama .calibration_data ke
dalam Modeltime Table. Kolom ini berisi prediksi model pada data uji
(test set) dan residualnya (selisih antara nilai aktual dan prediksi).
Data inilah yang disebut calibration data, yaitu hasil prediksi di luar
sampel pelatihan (out-of-sample), yang digunakan untuk mengukur seberapa
baik model memprediksi data baru.
Melalui proses ini, modeltime dapat menghitung akurasi
(seperti MAPE, RMSE, MAE) dan interval kepercayaan (confidence
intervals) untuk peramalan. Setelah dikalibrasi, data kalibrasi tersebut
akan terus “mengikuti” model dalam seluruh proses berikutnya (seperti
forecasting atau refitting), sehingga hasil ramalan yang dihasilkan
lebih terukur dan dapat dipercaya.
## # Modeltime Table
## # A tibble: 5 × 5
## .model_id .model .model_desc .type .calibration_data
## <int> <list> <chr> <chr> <list>
## 1 1 <fit[+]> ARIMA(2,0,0)(1,1,1)[12] WITH DRIFT Test <tibble [10 × 4]>
## 2 2 <fit[+]> ARIMA(2,0,0)(1,1,1)[12] WITH DRIFT… Test <tibble [10 × 4]>
## 3 3 <fit[+]> ETS(M,N,A) Test <tibble [10 × 4]>
## 4 4 <fit[+]> PROPHET Test <tibble [10 × 4]>
## 5 5 <fit[+]> LM Test <tibble [10 × 4]>
Ketika kita ingin menilai seberapa baik model bekerja, ada dua hal yang harus dilakukan:
Visualisasi hasil peramalan terhadap data uji (test set), yaitu dengan memplot prediksi model dibandingkan nilai aktual dari data uji, sehingga kita bisa melihat secara visual apakah ramalan model mengikuti pola data sebenarnya atau tidak.
Evaluasi akurasi pada data uji (out-of-sample accuracy), yaitu menghitung metrik seperti MAPE, RMSE, atau MAE untuk mengukur seberapa besar kesalahan model dalam memprediksi data yang belum pernah dilihat.
Visualisasi hasil peramalan:
calibration_tbl %>%
modeltime_forecast(
new_data = testing(splits),
actual_data = data
) %>%
plot_modeltime_forecast(
.legend_max_width = 30,
.interactive = TRUE
)Evaluasi akurasi:
Interpretasi:
Hasil evaluasi menunjukkan bahwa model ARIMA(2,0,0)(1,1,1)[12] with Drift w/ XGBoost Errors memberikan kinerja prediksi paling baik dibandingkan model ARIMA with Drift, ETS, Prophet, dan Linear Model (LM). Model hibrida tersebut menghasilkan MAE sebesar 67.247,67, MAPE 26,33%, MASE 0,36, sMAPE 28,30%, dan RMSE 87.034,21, dengan nilai R² sebesar 0,92. Nilai error yang lebih rendah pada sebagian besar metrik menunjukkan bahwa model hibrida mampu menghasilkan prediksi yang lebih dekat dengan nilai aktual pada periode pengujian.
Dibandingkan dengan model ARIMA with Drift, penambahan XGBoost untuk memodelkan error menghasilkan perbaikan kinerja. MAE menurun dari 70.084,63 menjadi 67.247,67 atau sekitar 4,05%, sedangkan RMSE menurun sekitar 3,37%. MAPE dan sMAPE juga mengalami penurunan masing-masing dari 26,67% menjadi 26,33% dan dari 29,54% menjadi 28,30%. Hasil ini memberikan indikasi bahwa XGBoost mampu menangkap informasi tambahan yang belum sepenuhnya direpresentasikan oleh struktur ARIMA.
Model ETS, Prophet, dan LM menunjukkan kinerja yang relatif lebih rendah berdasarkan sebagian besar metrik. ETS menghasilkan RMSE sebesar 108.376,29 dan R² 0,89, sedangkan Prophet menghasilkan RMSE 92.854,30 dan R² 0,89. LM memiliki MAPE sebesar 26,00%, tetapi menghasilkan RMSE yang relatif lebih tinggi, yaitu 94.718,97. Hal ini menunjukkan pentingnya menggunakan beberapa metrik secara simultan dalam evaluasi, karena satu ukuran kinerja saja belum tentu memberikan gambaran menyeluruh mengenai kemampuan prediksi suatu model.
Nilai MASE seluruh model yang berada di bawah satu menunjukkan bahwa model-model tersebut menghasilkan kesalahan yang lebih rendah dibandingkan benchmark naif yang digunakan dalam perhitungan MASE. Model ARIMA-XGBoost memiliki MASE terendah, yaitu 0,36. R² sebesar 0,92 menunjukkan bahwa model ARIMA-XGBoost dan ARIMA with Drift mampu menjelaskan proporsi variasi data pengujian yang relatif tinggi, akan tetapi R² sebaiknya tidak digunakan sebagai satu-satunya dasar pemilihan model karena evaluasi forecasting lebih relevan mempertimbangkan ukuran kesalahan prediksi.
Hasil pengujian secara keseluruhan memberikan indikasi bahwa
pendekatan ARIMA-XGBoost mampu meningkatkan akurasi prediksi
dibandingkan model ARIMA tunggal, namun peningkatan tersebut relatif
moderat sehingga belum cukup untuk menyatakan bahwa keunggulan model
hibrida bersifat universal atau signifikan secara statistik. Oleh karena
itu, perlu dilakukan walk-forward/rolling-origin validation, analisis
residual, dan pengujian perbedaan akurasi seperti Diebold–Mariano test
untuk memperkuat hasil pemodeln ini. Pendekatan tersebut penting untuk
memastikan bahwa peningkatan kinerja model hibrida bukan hanya
disebabkan oleh karakteristik satu periode pengujian tertentu.
Pada tahapan ini, model dilatih ulang menggunakan seluruh data dan melakukan peramalan 6 bulan ke depan.
refit_tbl <- calibration_tbl %>%
modeltime_refit(data = data)
refit_tbl %>%
modeltime_forecast(h = "6 months", actual_data = data) %>%
plot_modeltime_forecast(
.legend_max_width = 25,
.interactive = TRUE
) |>
plotly::layout(
legend = list(
orientation = "h",
y = -0.2,
x = 0.5,
xanchor = "center"
)
)Plot di atas menampilkan hasil peramalan data time series menggunakan beberapa model berbeda, yaitu ARIMA, ARIMA + XGBoost, ETS, Prophet, dan Linear Model (LM). Jika diperhatikan, data aktual menunjukkan pola musiman tahunan yang cukup kuat, dengan puncak dan lembah yang berulang setiap tahun. Pola ini menggambakan adanya siklus yang konsisten, misalnya, dalam konteks produksi padi, bisa jadi mewakili periode tanam dan panen yang terjadi secara berulang setiap tahun.
Dari hasil peramalan yang tampak di sisi kanan grafik (periode tahun 2025 hingga awal 2026), semua model secara umum mampu mengikuti pola musiman yang sama, namun dengan tingkat ketepatan yang berbeda-beda. Model ARIMA + XGBoost Errors terlihat paling menempel dengan data aktual dan memiliki area ketidakpastian (shading abu-abu) yang lebih sempit, menandakan bahwa prediksinya lebih stabil dan konsisten. Kombinasi antara ARIMA dan XGBoost ini memungkinkan model untuk menangkap pola linear sekaligus memperbaiki kesalahan residu yang bersifat non-linear, sehingga hasilnya lebih halus dan realistis.
Model ARIMA dengan Drift juga masih cukup akurat, namun prediksinya cenderung sedikit kaku dan tidak sefleksibel model hybrid ketika menghadapi perubahan musiman yang cepat. Model ETS (Error, Trend, Seasonality) pun masih mampu mengikuti pola, tetapi kadang tampak agak terlambat dalam merespons perubahan nilai aktual. Sementara itu, model Prophet dan Linear Model tidak begitu baik dalam menangkap pola musiman, prediksinya terlihat agak menyimpang dari data aktual, terutama pada bagian puncak dan lembah grafik.
Bagian abu-abu yang semakin melebar ke arah kanan menunjukkan selang kepercayaan (confidence interval) yang meningkat seiring waktu. Ini artinya, semakin jauh periode peramalan yang dilakukan, semakin besar pula ketidakpastian hasil prediksi, hal yang wajar dalam analisis deret waktu. Secara keseluruhan, ARIMA + XGBoost Errors menjadi model yang paling unggul karena mampu menghasilkan prediksi yang halus, stabil, dan paling mendekati pola aktual. Model ini juga menunjukkan bagaimana pendekatan hybrid antara metode statistik klasik dan pembelajaran mesin dapat meningkatkan akurasi forecasting, terutama pada data dengan pola musiman yang kuat.
Untuk menampilkan hasil forecast, gunakan kode sebagai berikut:
forecast_tbl <- refit_tbl %>%
modeltime_forecast(h = "6 months", actual_data = data) %>%
filter(.key == "prediction")
forecast_tbl## # Forecast Results
##
## # A tibble: 30 × 7
## .model_id .model_desc .key .index .value .conf_lo .conf_hi
## <int> <chr> <fct> <dttm> <dbl> <dbl> <dbl>
## 1 1 UPDATE: ARIMA(0… pred… 2026-05-01 00:00:00 3.78e5 196622. 558878.
## 2 1 UPDATE: ARIMA(0… pred… 2026-06-01 00:00:00 1.59e5 -21766. 340491.
## 3 1 UPDATE: ARIMA(0… pred… 2026-07-01 00:00:00 1.19e5 -61996. 300261.
## 4 1 UPDATE: ARIMA(0… pred… 2026-08-01 00:00:00 2.29e5 47794. 410050.
## 5 1 UPDATE: ARIMA(0… pred… 2026-09-01 00:00:00 4.50e5 269295. 631551.
## 6 1 UPDATE: ARIMA(0… pred… 2026-10-01 00:00:00 3.50e5 168429. 530685.
## 7 2 UPDATE: ARIMA(0… pred… 2026-05-01 00:00:00 3.83e5 207963. 557994.
## 8 2 UPDATE: ARIMA(0… pred… 2026-06-01 00:00:00 1.47e5 -27730. 322301.
## 9 2 UPDATE: ARIMA(0… pred… 2026-07-01 00:00:00 1.24e5 -50655. 299376.
## 10 2 UPDATE: ARIMA(0… pred… 2026-08-01 00:00:00 2.34e5 59135. 409166.
## # ℹ 20 more rows
Secara umum, modeltime adalah package yang powerfull
karena dalam satu workflow, kita bisa membuat berbagai model,
membandingkan hasilnya, dan melakukan forecast berdasarkan model yang
sudah dibuat, sangat efisien.
Tapi bicara hasilnya, kurang menggembirakan ya. Semua model yang digunakan punya error yang besar, bisa dilihat sendiri di tabel nilai MAPE-nya berapa, kemudian selang kepercayaanya juga ada yang melewati 0. Hal ini membuat hasil forecast menjadi tidak meyakinkan.
Nanti kita coba dengan model lain ya, di luar framework
modeltime.
Seluruh ide dalam tulisan ini adalah adaptasi dari artikel berjudul “Getting Started with Modeltime”, bisa diakses di url https://cran.r-project.org/web/packages/modeltime/vignettes/getting-started-with-modeltime.html.