# ==============================
# PRAKTIKUM 13 - TIME SERIES
# Forecasting Curah Hujan
# ==============================

library(readxl)
## Warning: package 'readxl' was built under R version 4.5.3
library(forecast)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(ggplot2)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(writexl)
library(tidyr)

# 1. Import data
data <- read_excel("D:/S2 IPB/Semester 4/Praktikum Stat for Sosial/PRAKTIKUM SESI UAS/P14/Data.xlsx")

# Cek data
head(data)
## # A tibble: 6 × 2
##   Tanggal             `Curah Hujan`
##   <dttm>                      <dbl>
## 1 2017-01-01 00:00:00          282 
## 2 2017-02-01 00:00:00          183 
## 3 2017-03-01 00:00:00          166.
## 4 2017-04-01 00:00:00          211.
## 5 2017-05-01 00:00:00          185.
## 6 2017-06-01 00:00:00          135.
str(data)
## tibble [83 × 2] (S3: tbl_df/tbl/data.frame)
##  $ Tanggal    : POSIXct[1:83], format: "2017-01-01" "2017-02-01" ...
##  $ Curah Hujan: num [1:83] 282 183 166 211 185 ...
# 2. Ubah menjadi data time series bulanan
hujan_ts <- ts(data$`Curah Hujan`,
               start = c(2017, 1),
               frequency = 12)
# 3. Plot data time series
autoplot(hujan_ts) +
  labs(title = "Plot Time Series Curah Hujan",
       x = "Tahun",
       y = "Curah Hujan") +
  theme_minimal()

# 4. Membuat model smoothing
# =========================================================
# MEMBUAT SEMUA MODEL
# =========================================================

# 1. Simple Exponential Smoothing
model_simple <- ets(hujan_ts, model = "ANN")

# 2. Holt's Linear Trend
model_holt <- ets(hujan_ts, model = "AAN")

# 3. Brown's Linear Trend
model_brown <- holt(hujan_ts,
                    h = 12,
                    exponential = FALSE,
                    damped = FALSE)

# 4. Damped Trend
model_damped <- ets(hujan_ts,
                    model = "AAN",
                    damped = TRUE)

# 5. Simple Seasonal
model_seasonal <- ets(hujan_ts, model = "ANA")

# 6. Winters Additive
model_win_add <- ets(hujan_ts, model = "AAA")

# 7. Winters Multiplicative
# Karena model multiplicative tidak boleh ada nilai 0
hujan_baru <- hujan_ts + 1

model_win_mult <- ets(hujan_baru, model = "MAM")
# 5. Forecast 12 bulan ke depan
fc_simple   <- forecast(model_simple, h = 12)
fc_holt     <- forecast(model_holt, h = 12)
fc_brown    <- model_brown
fc_damped   <- forecast(model_damped, h = 12)
fc_seasonal <- forecast(model_seasonal, h = 12)
fc_win_add  <- forecast(model_win_add, h = 12)
fc_win_mult <- forecast(model_win_mult, h = 12)
# =========================================================
# 5. FUNGSI AKURASI
# =========================================================

hitung_akurasi <- function(model, aktual){
  
  fitted_value <- as.numeric(fitted(model))
  
  MAD <- mean(abs(aktual - fitted_value), na.rm = TRUE)
  MSD <- mean((aktual - fitted_value)^2, na.rm = TRUE)
  MAPE <- mean(abs((aktual - fitted_value) / aktual), na.rm = TRUE) * 100
  
  return(c(MAD, MSD, MAPE))
}

hitung_akurasi_brown <- function(model, aktual){
  
  fitted_value <- as.numeric(model$fitted)
  
  MAD <- mean(abs(aktual - fitted_value), na.rm = TRUE)
  MSD <- mean((aktual - fitted_value)^2, na.rm = TRUE)
  MAPE <- mean(abs((aktual - fitted_value) / aktual), na.rm = TRUE) * 100
  
  return(c(MAD, MSD, MAPE))
}
# =========================================================
# 6. TABEL AKURASI MODEL
# =========================================================

aktual <- as.numeric(hujan_ts)

akurasi <- data.frame(
  Model = c("Simple",
            "Holt's Linear Trends",
            "Brown's linear trend",
            "Damped trend",
            "Simple Seasonal",
            "Winters' additive",
            "Winters' multiplicative"),
  
  rbind(
    hitung_akurasi(model_simple, aktual),
    hitung_akurasi(model_holt, aktual),
    hitung_akurasi_brown(model_brown, aktual),
    hitung_akurasi(model_damped, aktual),
    hitung_akurasi(model_seasonal, aktual),
    hitung_akurasi(model_win_add, aktual),
    hitung_akurasi(model_win_mult, aktual + 1)
  )
)

colnames(akurasi) <- c("Model", "MAD", "MSD", "MAPE")

akurasi <- akurasi %>%
  arrange(MAPE)

akurasi
##                     Model      MAD       MSD        MAPE
## 1 Winters' multiplicative 193.2617 232453.66    5542.932
## 2    Holt's Linear Trends 137.2623  33634.61  995088.680
## 3    Brown's linear trend 137.2663  33634.61  995488.072
## 4            Damped trend 137.3083  33599.97 1009667.820
## 5                  Simple 137.4444  33605.81 1011463.389
## 6         Simple Seasonal 116.7898  25022.18 1016290.203
## 7       Winters' additive 118.1566  25422.86 1058433.042
cat("Model terbaik berdasarkan MAPE adalah:",
    akurasi$Model[1])
## Model terbaik berdasarkan MAPE adalah: Winters' multiplicative
# =========================================================
# 7. TABEL HASIL FORECAST 12 BULAN
# =========================================================

hasil_forecast <- data.frame(
  Bulan = seq(as.Date("2023-12-01"),
              by = "month",
              length.out = 12),
  
  Simple = as.numeric(fc_simple$mean),
  Holt = as.numeric(fc_holt$mean),
  Brown = as.numeric(fc_brown$mean),
  Damped = as.numeric(fc_damped$mean),
  Simple_Seasonal = as.numeric(fc_seasonal$mean),
  Winters_Additive = as.numeric(fc_win_add$mean),
  Winters_Multiplicative = as.numeric(fc_win_mult$mean - 1)
)

hasil_forecast
##         Bulan   Simple     Holt    Brown   Damped Simple_Seasonal
## 1  2023-12-01 526.2805 523.8660 523.7625 526.3737        398.4404
## 2  2024-01-01 526.2805 521.3435 521.2407 526.4028        311.9300
## 3  2024-02-01 526.2805 518.8209 518.7190 526.4287        358.4291
## 4  2024-03-01 526.2805 516.2984 516.1973 526.4517        290.5097
## 5  2024-04-01 526.2805 513.7758 513.6755 526.4722        358.7827
## 6  2024-05-01 526.2805 511.2533 511.1538 526.4904        450.3155
## 7  2024-06-01 526.2805 508.7307 508.6321 526.5065        369.2043
## 8  2024-07-01 526.2805 506.2082 506.1103 526.5209        252.0884
## 9  2024-08-01 526.2805 503.6856 503.5886 526.5337        209.3446
## 10 2024-09-01 526.2805 501.1631 501.0669 526.5450        228.3205
## 11 2024-10-01 526.2805 498.6405 498.5451 526.5551        444.8381
## 12 2024-11-01 526.2805 496.1180 496.0234 526.5641        478.1367
##    Winters_Additive Winters_Multiplicative
## 1          408.8182              263.71819
## 2          328.0666              182.33103
## 3          390.1592              167.98569
## 4          335.7617              117.56665
## 5          398.0604              124.07468
## 6          502.7473              153.45375
## 7          431.7009              116.84293
## 8          305.3906               49.91876
## 9          285.1676               36.85410
## 10         311.9151               43.25642
## 11         533.9425              261.59579
## 12         562.9853              381.00743
# =========================================================
# 8. DATA AKTUAL DAN FITTED VALUE
# =========================================================

tanggal_aktual <- seq(as.Date("2017-01-01"),
                      by = "month",
                      length.out = length(hujan_ts))

data_fitted <- data.frame(
  Bulan = tanggal_aktual,
  Aktual = as.numeric(hujan_ts),
  Simple = as.numeric(fitted(model_simple)),
  Holt = as.numeric(fitted(model_holt)),
  Brown = as.numeric(fc_brown$fitted),
  Damped = as.numeric(fitted(model_damped)),
  Simple_Seasonal = as.numeric(fitted(model_seasonal)),
  Winters_Additive = as.numeric(fitted(model_win_add)),
  Winters_Multiplicative = as.numeric(fitted(model_win_mult) - 1)
)

head(data_fitted)
##        Bulan Aktual   Simple     Holt    Brown   Damped Simple_Seasonal
## 1 2017-01-01 282.00 274.7301 281.3341 281.3341 277.9523        195.4398
## 2 2017-02-01 183.00 281.5339 279.3866 279.3873 278.6778        309.8532
## 3 2017-03-01 165.50 189.3177 186.5331 186.5583 186.3892        142.4285
## 4 2017-04-01 210.75 167.0271 164.2513 164.2590 164.4068        228.8284
## 5 2017-05-01 184.75 207.9466 205.2224 205.2119 205.6303        306.1845
## 6 2017-06-01 135.25 186.2373 183.4683 183.4736 184.1682        129.8534
##   Winters_Additive Winters_Multiplicative
## 1         96.11674               152.7525
## 2        303.03930               192.3220
## 3        155.22001               133.6812
## 4        225.58127               156.6410
## 5        318.78563               223.2270
## 6        143.41943               159.5508
# =========================================================
# 9. GABUNG DATA AKTUAL, FITTED, DAN FORECAST
# =========================================================

data_fitted_long <- data_fitted %>%
  pivot_longer(cols = -Bulan,
               names_to = "Model",
               values_to = "Nilai") %>%
  mutate(Tipe = ifelse(Model == "Aktual", "Aktual", "Prediksi/Fitted"))

data_forecast_long <- hasil_forecast %>%
  pivot_longer(cols = -Bulan,
               names_to = "Model",
               values_to = "Nilai") %>%
  mutate(Tipe = "Forecast")

data_plot_all <- bind_rows(data_fitted_long, data_forecast_long)
# =========================================================
# 10. VISUALISASI AKTUAL, FITTED, DAN FORECAST SEMUA MODEL
# =========================================================

ggplot(data_plot_all,
       aes(x = Bulan,
           y = Nilai,
           color = Tipe,
           linetype = Tipe)) +
  geom_line(linewidth = 0.8, na.rm = TRUE) +
  facet_wrap(~ Model, scales = "free_y", ncol = 2) +
  labs(title = "Visualisasi Nilai Aktual, Prediksi, dan Forecast",
       x = "Bulan",
       y = "Curah Hujan",
       color = "Keterangan",
       linetype = "Keterangan") +
  theme_minimal() +
  theme(legend.position = "bottom")

# =========================================================
# VISUALISASI AKTUAL, PREDIKSI/FITTED, DAN FORECAST
# UNTUK SEMUA MODEL
# Merah = Aktual, Biru = Prediksi/Fitted, Hijau = Forecast
# =========================================================

library(ggplot2)
library(dplyr)
library(tidyr)

tanggal_aktual <- seq(as.Date("2017-01-01"),
                      by = "month",
                      length.out = length(hujan_ts))

tanggal_forecast <- seq(as.Date("2023-12-01"),
                        by = "month",
                        length.out = 12)

# Data aktual dan fitted semua model
data_plot <- data.frame(
  Bulan = rep(tanggal_aktual, 8),
  Nilai = c(
    as.numeric(hujan_ts),
    as.numeric(fitted(model_simple)),
    as.numeric(fitted(model_holt)),
    as.numeric(fc_brown$fitted),
    as.numeric(fitted(model_damped)),
    as.numeric(fitted(model_seasonal)),
    as.numeric(fitted(model_win_add)),
    as.numeric(fitted(model_win_mult) - 1)
  ),
  Model = c(
    rep("Aktual", length(hujan_ts)),
    rep("Simple", length(hujan_ts)),
    rep("Holt", length(hujan_ts)),
    rep("Brown", length(hujan_ts)),
    rep("Damped", length(hujan_ts)),
    rep("Simple Seasonal", length(hujan_ts)),
    rep("Winters Additive", length(hujan_ts)),
    rep("Winters Multiplicative", length(hujan_ts))
  ),
  Tipe = c(
    rep("Aktual", length(hujan_ts)),
    rep("Prediksi", length(hujan_ts) * 7)
  )
)

# Data forecast semua model
data_forecast <- data.frame(
  Bulan = rep(tanggal_forecast, 7),
  Nilai = c(
    as.numeric(fc_simple$mean),
    as.numeric(fc_holt$mean),
    as.numeric(fc_brown$mean),
    as.numeric(fc_damped$mean),
    as.numeric(fc_seasonal$mean),
    as.numeric(fc_win_add$mean),
    as.numeric(fc_win_mult$mean - 1)
  ),
  Model = c(
    rep("Simple", 12),
    rep("Holt", 12),
    rep("Brown", 12),
    rep("Damped", 12),
    rep("Simple Seasonal", 12),
    rep("Winters Additive", 12),
    rep("Winters Multiplicative", 12)
  ),
  Tipe = rep("Forecast", 12 * 7)
)

# Gabungkan aktual ke setiap model agar setiap panel punya garis merah
data_aktual_per_model <- data.frame(
  Bulan = rep(tanggal_aktual, 7),
  Nilai = rep(as.numeric(hujan_ts), 7),
  Model = rep(c("Simple",
                "Holt",
                "Brown",
                "Damped",
                "Simple Seasonal",
                "Winters Additive",
                "Winters Multiplicative"),
              each = length(hujan_ts)),
  Tipe = "Aktual"
)

# Data fitted tanpa panel aktual sendiri
data_fitted_model <- data_plot %>%
  filter(Model != "Aktual")

# Gabungkan semua
data_visualisasi <- bind_rows(
  data_aktual_per_model,
  data_fitted_model,
  data_forecast
)

# Visualisasi semua model
ggplot(data_visualisasi,
       aes(x = Bulan,
           y = Nilai,
           color = Tipe,
           linetype = Tipe)) +
  geom_line(linewidth = 0.8, na.rm = TRUE) +
  facet_wrap(~ Model, scales = "free_y", ncol = 2) +
  scale_color_manual(values = c(
    "Aktual" = "red",
    "Prediksi" = "blue",
    "Forecast" = "green"
  )) +
  scale_linetype_manual(values = c(
    "Aktual" = "solid",
    "Prediksi" = "dashed",
    "Forecast" = "dotted"
  )) +
  labs(title = "Visualisasi Nilai Aktual, Prediksi, dan Forecast Semua Model",
       x = "Bulan",
       y = "Curah Hujan",
       color = "Keterangan",
       linetype = "Keterangan") +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "bottom"
  )

# =========================================================
# VISUALISASI AKTUAL (MERAH)
# FITTED/PREDIKSI (BIRU)
# FORECAST (HIJAU)
# =========================================================

library(ggplot2)

# =========================================================
# CONTOH UNTUK SIMPLE SEASONAL
# =========================================================

# Data aktual
tanggal_aktual <- seq(as.Date("2017-01-01"),
                      by = "month",
                      length.out = length(hujan_ts))

# Data forecast
tanggal_forecast <- seq(as.Date("2024-01-01"),
                        by = "month",
                        length.out = 12)

# Membuat dataframe
plot_data <- data.frame(
  Bulan = c(tanggal_aktual,
            tanggal_aktual,
            tanggal_forecast),
  
  Nilai = c(as.numeric(hujan_ts),
             as.numeric(fitted(model_seasonal)),
             as.numeric(fc_seasonal$mean)),
  
  Tipe = c(rep("Aktual", length(hujan_ts)),
           rep("Prediksi", length(hujan_ts)),
           rep("Forecast", 12))
)

# =========================================================
# VISUALISASI
# =========================================================

ggplot(plot_data,
       aes(x = Bulan,
           y = Nilai,
           color = Tipe,
           linetype = Tipe)) +
  
  geom_line(linewidth = 1) +
  
  scale_color_manual(values = c(
    "Aktual" = "red",
    "Prediksi" = "blue",
    "Forecast" = "green"
  )) +
  
  labs(title = "Aktual vs Prediksi vs Forecast",
       x = "Bulan",
       y = "Curah Hujan") +
  
  theme_minimal() +
  
  theme(
    plot.title = element_text(hjust = 0.5,
                              face = "bold"),
    legend.position = "bottom"
  )

# =========================================================
# 11. VISUALISASI ACTUAL VS FORECAST MODEL SIMPLE SEASONAL
# =========================================================

plot_seasonal <- data.frame(
  Bulan = c(tanggal_aktual, hasil_forecast$Bulan),
  Nilai = c(as.numeric(hujan_ts),
            hasil_forecast$Simple_Seasonal),
  Tipe = c(rep("Aktual", length(hujan_ts)),
           rep("Forecast", 12))
)

ggplot(plot_seasonal,
       aes(x = Bulan,
           y = Nilai,
           color = Tipe)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  labs(title = "Actual vs Forecast - Simple Seasonal",
       x = "Bulan",
       y = "Curah Hujan",
       color = "Keterangan") +
  theme_minimal()

# =========================================================
# 12. VISUALISASI FORECAST SEMUA MODEL SAJA
# =========================================================

forecast_long <- hasil_forecast %>%
  pivot_longer(cols = -Bulan,
               names_to = "Model",
               values_to = "Forecast")

ggplot(forecast_long,
       aes(x = Bulan,
           y = Forecast,
           color = Model)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  labs(title = "Perbandingan Forecast Semua Model",
       x = "Bulan",
       y = "Curah Hujan") +
  theme_minimal() +
  theme(legend.position = "bottom")

# =========================================================
# 13. SIMPAN HASIL KE EXCEL
# =========================================================

write_xlsx(
  list(
    Akurasi_Model = akurasi,
    Forecast_12_Bulan = hasil_forecast,
    Aktual_dan_Fitted = data_fitted
  ),
  "Hasil_Praktikum_13_Time_Series.xlsx"
)