Data
# Membaca data
data <- read_excel("~/topik statistika/UAS TOPIK STAT/data harian BMKG.xlsx")
data$TANGGAL <- as.Date(data$TANGGAL, format = "%d-%m-%Y")
summary(data)
## TANGGAL jumlah_curah_hujan
## Min. :2025-05-01 Min. : 0.000
## 1st Qu.:2025-07-31 1st Qu.: 0.000
## Median :2025-10-30 Median : 0.200
## Mean :2025-10-30 Mean : 9.128
## 3rd Qu.:2026-01-29 3rd Qu.: 7.800
## Max. :2026-04-30 Max. :213.400
Ubah data ke time series
# Mengubah kolom 'jumlah_curah_hujan' menjadi objek time series
data.ts <- ts(data$jumlah_curah_hujan, start = 1)
# Menampilkan hasil time series
print(head(data.ts, 35))
## Time Series:
## Start = 1
## End = 35
## Frequency = 1
## [1] 0.0 0.0 3.0 42.2 0.0 0.0 3.0 3.7 0.0 0.0 0.8 27.0 0.0 55.2 0.0
## [16] 37.2 2.1 5.7 1.0 0.0 0.0 40.4 4.9 7.5 0.5 33.0 21.3 0.0 0.0 20.0
## [31] 0.0 1.6 0.0 0.0 0.0
Uji Pola Musiman
plot(data$TANGGAL, data.ts,
type = "l",
xaxt = "n",
xlab = "Bulan",
ylab = "Jumlah Curah Hujan (Yt)",
col = "blue",
lwd = 1.5,
main = "Time Series Plot Curah Hujan Harian (Mei 2025 - April 2026)")
titik_bulan <- seq(from = min(data$TANGGAL), to = max(data$TANGGAL), by = "1 month")
axis.Date(side = 1, at = titik_bulan, format = "%b %Y", las = 2, cex.axis = 0.8)
data$Bulan_Tahun <- format(data$TANGGAL, "%Y-%m")
data_bulanan <- aggregate(jumlah_curah_hujan ~ Bulan_Tahun, data = data, FUN = sum)
label_bulan <- format(as.Date(paste0(data_bulanan$Bulan_Tahun, "-01")), "%b %Y")
barplot(data_bulanan$jumlah_curah_hujan,
names.arg = label_bulan,
las = 2,
col = "skyblue",
main = "Distribusi Musiman Jumlah Curah Hujan (Mei 2025 - April 2026)",
ylab = "Jumlah Curah Hujan (Yt)",
cex.names = 0.8)
berdasarkan plot time series dan diagram distribusi musiman jumlah curah
hujan tidak terlihat pola musiman pada data sehingga tidak representatif
jika menggunakan model SARIMA maka analisis selajutnya akan dilakukan
menggunakan model AR,MA,ARMA, dan ARIMA
Splitting data
80% Data Train = 292 Hari, 20% Data Test = 73 Hari
train.ts <- window(data.ts, end = 292)
test.ts <- window(data.ts, start = 293)
Uji kestasioneran varians data
# Stasioneritas Varians (Box-Cox)
lambda_opt <- BoxCox.lambda(train.ts)
## Warning in guerrero(x, lower, upper): Guerrero's method for selecting a Box-Cox
## parameter (lambda) is given for strictly positive data.
cat("Nilai Lambda Box-Cox:", round(lambda_opt, 4), "\n")
## Nilai Lambda Box-Cox: 0.0283
Uji kestasioneran rataan data
Mengidentifikasi kestasioneran data dilakukan dengan uji ADF. Uji Augmented Dickey-Fuller (ADF) adalah salah satu alat identifikasi untuk menguji kestasioneran data dan memiliki hipotesis sebagai berikut:
\[H_0: \text{Data tidak stasioner (mengandung unit root)}\] \[H_1: \text{Data stasioner (tidak mengandung unit root)}\]
cat("\n--- Uji ADF Data Train ---\n")
##
## --- Uji ADF Data Train ---
print(adf.test(train.ts))
## Warning in adf.test(train.ts): p-value smaller than printed p-value
##
## Augmented Dickey-Fuller Test
##
## data: train.ts
## Dickey-Fuller = -4.6802, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary
Berdasarkan hasil uji ADF dengan taraf signifikansi \(\alpha = 5\%\) di atas dapat diketahui bersama bahwa \(p-value = 0.01 < \alpha = 0.05\) sehingga keputusan yang diambil adalah Tolak \(H_0\) artinya data yang digunakan merupakan data yang stasioner.
Identifikasi kandidat model ARIMA
Identifikasi kandidat model diperoleh berdasarkan nilai p dan q dimana nilai d=0
acf(train.ts, main="ACF Data Train")
Berdasarkan plot ACF terlihat bahwa plot cuts off setelah lag ke-10
sehingga kandidat model yang diperoleh adalah ARMA(0,0,10)
pacf(train.ts, main="PACF Data Train")
Berdasarkan plot PACF di atas kandidat model yang diperoleh adalah
ARMA(8,0,0)
cat("\n--- Extended ACF (EACF) ---\n")
##
## --- Extended ACF (EACF) ---
eacf(train.ts)
## AR/MA
## 0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o x o o x o x o o o o
## 1 x o o o x o o x o x o o o o
## 2 x x o o x o x o o x o o o o
## 3 x o o o x o x o o x o o o o
## 4 x x x x x o x o o x o o o o
## 5 o o x o x o o x o o o o o o
## 6 x o x o x o o x o o o o o o
## 7 x o x x x o o x x o o o o o
Berdasarkan hasil EACF di atas kandidat model yang diperoleh adalah ARMA(1,0,1),ARMA(0,0,1), dan ARMA(2,0,2)
Dibandingkan dengan auto.arima
auto.arima(train.ts, trace = TRUE)
##
## Fitting models using approximations to speed things up...
##
## ARIMA(2,1,2) with drift : 2605.718
## ARIMA(0,1,0) with drift : 2779.127
## ARIMA(1,1,0) with drift : 2701.139
## ARIMA(0,1,1) with drift : 2599.393
## ARIMA(0,1,0) : 2777.099
## ARIMA(1,1,1) with drift : 2602.462
## ARIMA(0,1,2) with drift : 2601.448
## ARIMA(1,1,2) with drift : Inf
## ARIMA(0,1,1) : 2597.572
## ARIMA(1,1,1) : 2600.601
## ARIMA(0,1,2) : 2599.598
## ARIMA(1,1,0) : 2699.097
## ARIMA(1,1,2) : Inf
##
## Now re-fitting the best model(s) without approximations...
##
## ARIMA(0,1,1) : 2605.125
##
## Best model: ARIMA(0,1,1)
## Series: train.ts
## ARIMA(0,1,1)
##
## Coefficients:
## ma1
## -0.9280
## s.e. 0.0334
##
## sigma^2 = 444.6: log likelihood = -1300.54
## AIC=2605.08 AICc=2605.12 BIC=2612.43
Berdasarkan hasil dari auto arima diperoleh best model yaitu ARIMA(0,1,1)
Pemilihan kandidat model terbaik
# ARMA(0,0,10)
arma0010 <- arima(train.ts, order = c(0,0,10), include.mean = TRUE, method = "ML")
arma0010
##
## Call:
## arima(x = train.ts, order = c(0, 0, 10), include.mean = TRUE, method = "ML")
##
## Coefficients:
## ma1 ma2 ma3 ma4 ma5 ma6 ma7 ma8 ma9
## 0.0660 0.0485 -0.0130 -0.0110 0.3067 0.0310 -0.0317 0.1366 0.0492
## s.e. 0.0584 0.0583 0.0588 0.0582 0.0578 0.0559 0.0571 0.0532 0.0654
## ma10 intercept
## 0.1457 9.2496
## s.e. 0.0561 1.9861
##
## sigma^2 estimated as 392.6: log likelihood = -1286.78, aic = 2595.56
# ARMA(8,0,0)
arma800 <- arima(train.ts, order = c(8,0,0), include.mean = TRUE, method = "ML")
arma800
##
## Call:
## arima(x = train.ts, order = c(8, 0, 0), include.mean = TRUE, method = "ML")
##
## Coefficients:
## ar1 ar2 ar3 ar4 ar5 ar6 ar7 ar8
## 0.0665 0.0579 -0.0221 0.0094 0.3154 0.0181 -0.0414 0.1295
## s.e. 0.0579 0.0579 0.0579 0.0552 0.0552 0.0583 0.0581 0.0579
## intercept
## 9.2212
## s.e. 2.4461
##
## sigma^2 estimated as 394.9: log likelihood = -1287.56, aic = 2593.13
# ARMA(1,0,1)
arma101 <- arima(train.ts, order = c(1,0,1), include.mean = TRUE, method = "ML")
arma101
##
## Call:
## arima(x = train.ts, order = c(1, 0, 1), include.mean = TRUE, method = "ML")
##
## Coefficients:
## ar1 ma1 intercept
## 0.9407 -0.8654 9.2524
## s.e. 0.0381 0.0539 2.6845
##
## sigma^2 estimated as 434.1: log likelihood = -1301.1, aic = 2608.2
# ARMA(0,0,1)
arma001 <- arima(train.ts, order = c(0,0,1), include.mean = TRUE, method = "ML")
arma001
##
## Call:
## arima(x = train.ts, order = c(0, 0, 1), include.mean = TRUE, method = "ML")
##
## Coefficients:
## ma1 intercept
## 0.0820 9.2491
## s.e. 0.0547 1.3475
##
## sigma^2 estimated as 453.2: log likelihood = -1307.3, aic = 2618.61
# ARMA(2,0,2)
arma202 <- arima(train.ts, order = c(2,0,2), include.mean = TRUE, method = "ML")
arma202
##
## Call:
## arima(x = train.ts, order = c(2, 0, 2), include.mean = TRUE, method = "ML")
##
## Coefficients:
## ar1 ar2 ma1 ma2 intercept
## 0.1706 0.7271 -0.0777 -0.6888 9.2467
## s.e. 0.2680 0.2500 0.2615 0.2229 2.6955
##
## sigma^2 estimated as 433.6: log likelihood = -1300.96, aic = 2611.92
# ARIMA(0,1,1)
arima011 <- arima(train.ts, order = c(0,1,1), include.mean = TRUE, method = "ML")
arima011
##
## Call:
## arima(x = train.ts, order = c(0, 1, 1), include.mean = TRUE, method = "ML")
##
## Coefficients:
## ma1
## -0.9280
## s.e. 0.0334
##
## sigma^2 estimated as 443.1: log likelihood = -1300.54, aic = 2603.08
KndidatModelARIMA <- c("ARMA(0,0,10)", "ARMA(8,0,0)", "ARMA(1,0,1)",
"ARMA(0,0,1)", "ARMA(2,0,2)", "ARIMA(0,1,1)")
AICKandidatModel <- c(arma0010$aic, arma800$aic, arma101$aic,
arma001$aic, arma202$aic, arima011$aic)
compmodelARIMA <- data.frame(
"Kandidat Model" = KndidatModelARIMA,
"Nilai AIC" = round(AICKandidatModel, 2),
check.names = FALSE
)
compmodelARIMA
## Kandidat Model Nilai AIC
## 1 ARMA(0,0,10) 2595.56
## 2 ARMA(8,0,0) 2593.13
## 3 ARMA(1,0,1) 2608.20
## 4 ARMA(0,0,1) 2618.61
## 5 ARMA(2,0,2) 2611.92
## 6 ARIMA(0,1,1) 2603.08
Model terbaik diperoleh Berdasarkan nilai AIC terkecil dari kandidat model. Oleh karena itu, Model terbaik yang diperoleh yaitu ARMA(8,0,0)
Model ARMA(8,0,0), maka \(Y_t\) diperoleh dari penjabaran operator backshift sebagai berikut: \[ \begin{aligned} \phi_p(B)(1 - B)^d Y_t &= \mu + \theta_q(B) e_t \\ (1 - \phi_1 B - \phi_2 B^2 - \phi_3 B^3 - \phi_4 B^4 - \phi_5 B^5 - \phi_6 B^6 - \phi_7 B^7 - \phi_8 B^8)(1 - B)^0 Y_t &= \mu + (1) e_t \\ (1 - \phi_1 B - \phi_2 B^2 - \phi_3 B^3 - \phi_4 B^4 - \phi_5 B^5 - \phi_6 B^6 - \phi_7 B^7 - \phi_8 B^8) Y_t &= \mu + e_t \\ Y_t - \phi_1 B Y_t - \phi_2 B^2 Y_t - \phi_3 B^3 Y_t - \phi_4 B^4 Y_t - \phi_5 B^5 Y_t - \phi_6 B^6 Y_t - \phi_7 B^7 Y_t - \phi_8 B^8 Y_t &= \mu + e_t \\ Y_t - \phi_1 Y_{t-1} - \phi_2 Y_{t-2} - \phi_3 Y_{t-3} - \phi_4 Y_{t-4} - \phi_5 Y_{t-5} - \phi_6 Y_{t-6} - \phi_7 Y_{t-7} - \phi_8 Y_{t-8} &= \mu + e_t \\ Y_t &= \mu + \phi_1 Y_{t-1} + \phi_2 Y_{t-2} + \phi_3 Y_{t-3} + \phi_4 Y_{t-4} + \phi_5 Y_{t-5} + \phi_6 Y_{t-6} + \phi_7 Y_{t-7} + \phi_8 Y_{t-8} + e_t \end{aligned} \]
Diagnostic model
ARMA800diag <- stats::arima(train.ts, order = c(8,0,0), method = "ML")
checkresiduals(ARMA800diag)
##
## Ljung-Box test
##
## data: Residuals from ARIMA(8,0,0) with non-zero mean
## Q* = 1.3013, df = 3, p-value = 0.7288
##
## Model df: 8. Total lags used: 11
sisaan <- arma800$residuals
Berdasarkan plot di atas terlihat bahwa sisaan tidak mengikuti sebaran normal. Selanjutnya, ditinjau dari plot ACF dan PACF terlihat bahwa tidak ada lag yang signifikan. Hal tersebut menunjukkan bahwa tidak ada gejala autokorelasi pada sisaan.
Uji normalitas data
\[H_0: \text{sisaan menyebar normal}\]
\[H_1: \text{sisaan tidak mengikuti sebaran normal}\]
# Uji normalitas data
ks.test(sisaan,"pnorm")
## Warning in ks.test.default(sisaan, "pnorm"): ties should not be present for the
## one-sample Kolmogorov-Smirnov test
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: sisaan
## D = 0.71594, p-value < 2.2e-16
## alternative hypothesis: two-sided
Berdasarkan hasil Kolmogorov-Smirnov Test di atas, didapatkan nilai p-value < \(\alpha = 0.05\), maka keputusan yang diambil adalah tolak \(H_0\). Secara matematis, hal ini membuktikan bahwa sisaan dari model tidak mengikuti sebaran normal.
Uji nilai tengah sisaan
\[H_0: \mu = 0\] \[H_1: \mu \neq 0\]
# Uji nilai tengah sisaan
t.test(sisaan, mu = 0, alternative = "two.sided")
##
## One Sample t-test
##
## data: sisaan
## t = 0.011325, df = 291, p-value = 0.991
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
## -2.279553 2.305938
## sample estimates:
## mean of x
## 0.01319249
Berdasarkan hasil uji-t nilai p-value > \(\alpha = 0.05\), maka terima \(H_0\). Ini menunjukkan bahwa secara statistik, nilai harapan (expected value) dari galat terbukti sama dengan nol.
Uji autokorelasi
\[H_0: \text{ tidak ada autokorelasi}\] \[H_1: \text{terdapat autokorelasi}\]
# Uji autokorelasi
Box.test(sisaan, lag = 23 ,type = "Ljung")
##
## Box-Ljung test
##
## data: sisaan
## X-squared = 6.7262, df = 23, p-value = 0.9996
Hasil pengujian memberikan nilai p-value > \(\alpha = 0.05\), maka diambil keputusan terima \(H_0\). Hal ini menyimpulkan bahwa sisaan bersifat saling bebas / tidak terdapat autokorelasi (white noise)
Peramalan
h_test <- 73
forecasting_arma0010 <- predict(arma0010, n.ahead = h_test)
forecasting_arma800 <- predict(arma800, n.ahead = h_test)
forecasting_arma101 <- predict(arma101, n.ahead = h_test)
forecasting_arma001 <- predict(arma001, n.ahead = h_test)
forecasting_arma202 <- predict(arma202, n.ahead = h_test)
forecasting_arima011 <- predict(arima011, n.ahead = h_test)
# Menampilkan hasil forecast model terbaik (ARMA 8,0,0) sebagai data frame
hasilforecasting <- as.data.frame(forecasting_arma800)
head(hasilforecasting)
## pred se
## 1 7.118789 19.87213
## 2 17.684006 19.91595
## 3 6.694200 19.95447
## 4 5.068215 19.95643
## 5 10.280688 19.95753
## 6 7.442357 20.91339
# 2. Visualisasi hasil peramalan model terbaik (ARMA 8,0,0)
ts.plot(train.ts, forecasting_arma800$pred,
ylab = "Jumlah Curah Hujan", xlab = "Waktu (Indeks Hari)",
col = c("blue", "red"),
main = "Visualisasi Hasil Peramalan ARMA(8,0,0)")
# Menambahkan batas kepercayaan (Upper 95% dan Lower 95%) menggunakan Standard Error
lines(forecasting_arma800$pred + 1.96 * forecasting_arma800$se, col = "green", lty = 2)
lines(forecasting_arma800$pred - 1.96 * forecasting_arma800$se, col = "green", lty = 2)
legend("topleft",
legend = c("Data Aktual (Train)", "Forecast", "Upper/Lower 95%"),
col = c("blue", "red", "green"),
lty = c(1, 1, 2),
cex = 0.7, inset = 0.02)
Evaluasi Akurasi hasil peramalan
akurasi.arma0010 <- accuracy(forecasting_arma0010$pred, test.ts)
akurasi.arma800 <- accuracy(forecasting_arma800$pred, test.ts)
akurasi.arma101 <- accuracy(forecasting_arma101$pred, test.ts)
akurasi.arma001 <- accuracy(forecasting_arma001$pred, test.ts)
akurasi.arma202 <- accuracy(forecasting_arma202$pred, test.ts)
akurasi.arima011 <- accuracy(forecasting_arima011$pred, test.ts)
KandidatModel <- c("ARMA(0,0,10)", "ARMA(8,0,0)", "ARMA(1,0,1)",
"ARMA(0,0,1)", "ARMA(2,0,2)", "ARIMA(0,1,1)")
RMSE_Testing <- c(akurasi.arma0010[,"RMSE"], akurasi.arma800[,"RMSE"],
akurasi.arma101[,"RMSE"], akurasi.arma001[,"RMSE"],
akurasi.arma202[,"RMSE"], akurasi.arima011[,"RMSE"])
# Menggabungkan semuanya ke dalam Data Frame
EvaluasiAkurasi <- data.frame(
"Kandidat Model" = KandidatModel,
"RMSE" = round(RMSE_Testing, 2),
check.names = FALSE
)
# Menampilkan Tabel Komparasi Akhir
cat("\n--- TABEL EVALUASI AKURASI MODEL ---\n")
##
## --- TABEL EVALUASI AKURASI MODEL ---
print(EvaluasiAkurasi)
## Kandidat Model RMSE
## 1 ARMA(0,0,10) 21.20
## 2 ARMA(8,0,0) 21.23
## 3 ARMA(1,0,1) 20.85
## 4 ARMA(0,0,1) 20.94
## 5 ARMA(2,0,2) 20.83
## 6 ARIMA(0,1,1) 22.21
Hasil evaluasi menunjukkan bahwa peramalan pada set data pengujian memposisikan model ARMA(2,0,2) dengan nilai simpangan galat (RMSE) paling minimum sebesar 20,83. Namun, filosofi pemodelan dalam pendekatan Box-Jenkins menekankan pada pemilihan arsitektur model berdasarkan keseimbangan terbaik antara parsimony (efisiensi parameter) pada data training dan ketepatan prediksi pada data testing. Mengacu pada signifikansi nilai efisiensi informasi dari kriteria AIC, model ARMA(8,0,0) terpilih sebagai instrumen model dasar yang paling optimal secara struktural, meskipun memiliki angka galat (RMSE sebesar 21.23) yang sedikit berada di bawah model ARMA(2,0,2) pada fase pengujian. Oleh karenanya, ARMA(8,0,0) ditetapkan sebagai model paling representatif dalam kerangka analitik ini.