# ==========================================
# PROJECT DATA CHALLENGE (ANALISIS DATA)
# ==========================================

# 1. Load Library 
library(readxl)
## Warning: package 'readxl' was built under R version 4.5.1
library(tseries)
## Warning: package 'tseries' was built under R version 4.5.2
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(forecast)
## Warning: package 'forecast' was built under R version 4.5.3
library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
# 2. Input Data
inflasi <- read_excel("C:/Users/HP141024/Documents/Kuliah Semester 5/Data Challenge/Data_Inflasi_DC.xlsx")

str(inflasi)
## tibble [284 × 3] (S3: tbl_df/tbl/data.frame)
##  $ No          : num [1:284] 1 2 3 4 5 6 7 8 9 10 ...
##  $ Periode     : chr [1:284] "Januari 2003" "Februari 2003" "Maret 2003" "April 2003" ...
##  $ Data Inflasi: num [1:284] 8.68 7.6 7.17 7.62 7.15 6.98 6.27 6.51 6.33 6.48 ...
summary(inflasi)
##        No           Periode           Data Inflasi   
##  Min.   :  1.00   Length:284         Min.   :-0.090  
##  1st Qu.: 71.75   Class :character   1st Qu.: 3.042  
##  Median :142.50   Mode  :character   Median : 4.475  
##  Mean   :142.50                      Mean   : 5.249  
##  3rd Qu.:213.25                      3rd Qu.: 6.678  
##  Max.   :284.00                      Max.   :18.380
# 3. Pre-processing Data
# Mengecek apakah terdapat nilai kosong (Missing Values / NA)
jumlah_na <- sum(is.na(inflasi$`Data Inflasi`))
cat("Jumlah data NA (kosong):", jumlah_na, "\n")
## Jumlah data NA (kosong): 0
# 4. Model Time Series
# Menentukan start tahun 2003 bulan 1 (Januari)
ts_inflasi <- ts(
  inflasi$`Data Inflasi`,
  start = c(2003, 1), 
  frequency = 12
)

# 5. Exploratory Data Analysis (EDA) & Visualisasi
# Plot deret waktu dasar
ts.plot(ts_inflasi, main = "Plot Inflasi Bulanan", 
        ylab = "Inflasi (%)", xlab = "Tahun", 
        col = "blue", lwd = 2)

# Dekomposisi Data (melihat unsur trend, musiman dan acak)
dekomposisi <- decompose(ts_inflasi)
plot(dekomposisi)

# Plot ACF dan PACF 
acf(ts_inflasi, main = "Plot ACF")

pacf(ts_inflasi, main = "Plot PACF")

# 6. Uji Stasioneritas (Augmented Dickey-Fuller Test)
# H0: Data tidak stasioner (mengandung akar unit)
# H1: Data stasioner
# Tolak H0 jika p-value < 0.05
adf.test(ts_inflasi)
## Warning in adf.test(ts_inflasi): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  ts_inflasi
## Dickey-Fuller = -4.4595, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary
# 7. Pemodelan SARIMA
# Mencari model terbaik berdasarkan nilai AIC terkecil
model_ts <- auto.arima(ts_inflasi, seasonal = TRUE)
summary(model_ts)
## Series: ts_inflasi 
## ARIMA(2,1,2)(0,0,1)[12] with drift 
## 
## Coefficients:
##           ar1      ar2     ma1     ma2     sma1    drift
##       -0.5539  -0.6636  0.7001  0.6263  -0.8004  -0.0240
## s.e.   0.2614   0.1666  0.2678  0.2113   0.0445   0.0108
## 
## sigma^2 = 0.5106:  log likelihood = -309.76
## AIC=633.52   AICc=633.93   BIC=659.04
## 
## Training set error measures:
##                       ME      RMSE       MAE       MPE     MAPE      MASE
## Training set 0.005939128 0.7056905 0.3732131 0.8590653 10.04494 0.1403115
##                     ACF1
## Training set 0.002853482
# 8. Uji Asumsi Residual (Model Diagnostik)

## a. Uji Autokorelasi Residual (Ljung-Box Test)
# H0: Tidak ada autokorelasi pada residual (Model sudah cukup baik)
# H1: Terdapat autokorelasi pada residual
# Tolak H0 jika p-value < 0.05
Box.test(model_ts$residuals, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  model_ts$residuals
## X-squared = 0.0023369, df = 1, p-value = 0.9614
checkresiduals(model_ts)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(2,1,2)(0,0,1)[12] with drift
## Q* = 15.772, df = 19, p-value = 0.6724
## 
## Model df: 5.   Total lags used: 24
## b. Uji Normalitas Residual (Shapiro-Wilk Test)
# H0: Residual berdistribusi normal
# H1: Residual tidak berdistribusi normal
# Tolak H0 jika p-value < 0.05
shapiro.test(model_ts$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  model_ts$residuals
## W = 0.64248, p-value < 2.2e-16
# 9. Forecasting menggunakan seluruh data

# Periode ramalan
h <- 4

# Ramalan SARIMA
ramalan_sarima <- forecast(model_ts, h)
print(ramalan_sarima)
##          Point Forecast     Lo 80    Hi 80      Lo 95    Hi 95
## Sep 2026       3.180168 2.2644296 4.095907  1.7796669 4.580669
## Oct 2026       2.932595 1.5396769 4.325512  0.8023109 5.062878
## Nov 2026       2.910842 1.2296502 4.592035  0.3396807 5.482004
## Dec 2026       2.788644 0.8757752 4.701513 -0.1368365 5.714125
# Ramalan SMA
# Function Forecasting SMA
forecast_sma <- function(data, h, k) {
  data_baru <- as.numeric(data)
  ramalan <- numeric(h)
  
  for (i in 1:h) {
    ramalan[i] <- mean(tail(data_baru, k), na.rm = TRUE)
    data_baru <- c(data_baru, ramalan[i])
  }
  
  return(ramalan)
}

# Forecasting 4 bulan ke depan dengan MA(3)
ramalan_sma <- forecast_sma(ts_inflasi, h, k = 3)
print(ramalan_sma)
## [1] 3.136667 3.068889 3.131852 3.112469
# Periode 
nama_bulan <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
periode <- paste(nama_bulan[cycle(ramalan_sarima$mean)],
                 floor(time(ramalan_sarima$mean)))

# Tabel hasil peramalan
hasil_ramalan <- data.frame(
  Periode = periode,
  SARIMA = as.numeric(ramalan_sarima$mean),
  SMA = as.numeric(ramalan_sma)
)
print(hasil_ramalan)
##    Periode   SARIMA      SMA
## 1 Sep 2026 3.180168 3.136667
## 2 Oct 2026 2.932595 3.068889
## 3 Nov 2026 2.910842 3.131852
## 4 Dec 2026 2.788644 3.112469
# 10. Visualisasi Hasil Ramalan

# Visualisasi Metode SARIMA

plot(ramalan_sarima, 
     main = "Peramalan Inflasi 4 Bulan Kedepan", 
     ylab = "Inflasi (%)", 
     xlab = "Tahun")

# Visualisasi Peramalan 4 Bulan ke Depan
plot(
  ramalan_sarima,
  include = 12,
  main = "Peramalan Inflasi 4 Bulan ke Depan",
  ylab = "Inflasi (%)",
  xlab = "",
  fcol = "blue",
  shadecols = c("#cce6ff", "#99ccff"),
  xaxt = "n"
)

# Membuat label bulan dan tahun
waktu_plot <- c(tail(time(ts_inflasi), 12), time(ramalan_sarima$mean))
awal <- as.Date(sprintf("%d-%02d-01", floor(waktu_plot[1]), cycle(tail(ts_inflasi, 12))[1]))
label_waktu <- format(seq(awal, by = "month", length.out = length(waktu_plot)),"%b %Y")
axis(1, at = waktu_plot, labels = label_waktu, las = 2, cex.axis = 0.8)
grid()

# Visualisasi Metode SMA

sma <- rollmean(ts_inflasi, k = 3, align = "right", fill = NA)

# Menggabungkan SMA historis dan hasil ramalan
sma_gabungan <- ts(
  c(as.numeric(sma), as.numeric(ramalan_sma)),
  start = start(ts_inflasi),
  frequency = frequency(ts_inflasi)
)

# Visualisasi data 
ts.plot(
  ts_inflasi, sma_gabungan,
  col = c("black", "steelblue"),
  lwd = c(1, 2),
  main = "Peramalan Inflasi Menggunakan SMA(3)",
  ylab = "Inflasi (%)",
  xlab = "Tahun"
)

legend(
  "topleft",
  legend = c("Data Aktual", "SMA(3) dan Ramalan"),
  col = c("black", "steelblue"),
  lty = 1,
  lwd = c(1, 2)
)

# Perbandingan Error SARIMA dan SMA(3)

# Membagi data latih dan data uji
h_uji <- 6
n <- length(ts_inflasi)

data_latih <- ts_inflasi[1:(n - h_uji)]
data_uji <- as.numeric(tail(ts_inflasi, h_uji))

# Ramalan SARIMA pada data uji
model_sarima_uji <- auto.arima(data_latih, seasonal = TRUE)
pred_sarima <- as.numeric(
  forecast(model_sarima_uji, h = h_uji)$mean
)

# Ramalan SMA(3) pada data uji
pred_sma <- forecast_sma(data_latih, h = h_uji, k = 3)

# Fungsi menghitung error
hitung_error <- function(aktual, prediksi) {
  c(
    MAE = mean(abs(aktual - prediksi)),
    RMSE = sqrt(mean((aktual - prediksi)^2)),
    MAPE = mean(abs(
      (aktual[aktual != 0] - prediksi[aktual != 0]) /
        aktual[aktual != 0]
    )) * 100
  )
}

# Membandingkan error
hasil_error <- rbind(
  SARIMA = hitung_error(data_uji, pred_sarima),
  SMA3 = hitung_error(data_uji, pred_sma)
)

cat("Perbandingan Error SARIMA dan SMA(3):\n")
## Perbandingan Error SARIMA dan SMA(3):
print(round(hasil_error, 4))
##           MAE   RMSE    MAPE
## SARIMA 1.8715 1.9010 63.3011
## SMA3   0.9415 1.0315 32.7726